質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
オブジェクト

オブジェクト指向において、データとメソッドの集合をオブジェクト(Object)と呼びます。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

3回答

330閲覧

オブジェクトの中のオブジェクトにアクセスしたい

takopo

総合スコア484

オブジェクト

オブジェクト指向において、データとメソッドの集合をオブジェクト(Object)と呼びます。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2020/02/16 23:32

JavaScriptで変数の作成の仕方で分からないところがあり質問させていただきました。
下のようなオブジェクトを作成していまして、food.fruitsで「フルーツ」という文字列、fruits.appleで「りんご」という文字列にアクセスできます。

JavaScript

1const food = { 2 fruits: 'フルーツ' 3}; 4 5const fruits = { 6 banana: 'バナナ', 7 apple : 'りんご', 8 orange: 'みかん' 9};

今このオブジェクトは別々なのですが、これを一つにまとめて、

  • food.fruitsで、「フルーツ」という文字列
  • food.fruits.appleで、「りんご」という文字列

にアクセスできればなと思っております。

下のような形で作成してみたのですが、これはエラーが出てしまいました・・・

JavaScript

1const food = { 2 fruits = 'フルーツ', 3 { 4 banana: 'バナナ', 5 apple : 'りんご', 6 orange: 'みかん' 7 } 8}

いろいろ試してみたのですが、良い方法が分からず困っております。
もし詳しい方がいらっしゃいましたらご教授いただけますと助かります。
よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

thyda.eiqau

2020/02/17 00:23 編集

オブジェクトの中のオブジェクトにアクセスしたい、という命題は、food.fruitsというオブジェクトにアクセスしたいという事ですよね。 > food.fruitsで「フルーツ」という文字列 というのは、food.fruitsがオブジェクトではなく文字列であることを求めていますが、ここの矛盾についてはどうお考えでしょうか。
guest

回答3

0

良い方法が分からず困っております

ベストプラクティスを知りたいということですね。
データの持ち方として「一貫性を持たせる」事が重要になります。

一つの変数・プロパティは一つの値「文字列 or オブジェクト」しか格納できませんので、
名前と子供要素の両方が持ちたければ下記のような「名前」と「子孫」を定義して一生深く掘っていく仕組みを作るのが良いでしょう。

js

1const food = { 2 name: '食べ物', 3 children: { 4 fruits: { 5 name: 'フルーツ', 6 children: { 7 banana: { 8 name: 'バナナ', 9 children: {} 10 }, 11 apple : { 12 name: 'りんご', 13 children: {} 14 }, 15 mandarin: { 16 name: 'みかん', 17 children: [] 18 }, 19 } 20 } 21 } 22}

いやちょっとまって?
これ使いにくいでしょ?

私はfood.fruits"フルーツ"を取り出したいのに、
なんでfood.children.fruits.nameにしなきゃいけないんだ?

フルーツはまだいいわ
food.fruits.apple"アップル"に辿り着こうと思ったら
food.children.fruits.children.apple.nameとかありえんわ!

こうなると思います。


ではどうするか?
検索関数もセットで準備しましょう。

js

1// childrenを再帰的に掘っていく関数を実装 2const getItem = (list, path) => { 3 const paths = path.split('.'); 4 // パスかリストのどちらかを掘り終えたら検索終了 5 if (!paths[0]) return list; 6 if (!list.children) return {}; 7 8 // null値やundefined値はプロパティを所持していないので 9 // アクセスを試みた時点でエラーとなる現象を回避する為に空のオブジェクトを返させる 10 const result = list.children[paths[0]] || {}; 11 12 // 先頭要素だけ消し飛ばして更に子供要素に入っていく 13 return getItem(result, paths.slice(1).join('.')); 14} 15 16// food.fruits.appleで検索したいのでlistという変数を作って更にネストさせる 17const list = { 18 name: 'リスト', 19 children: { 20 food: { 21 name: '食べ物', 22 children: { 23 fruits: { 24 name: 'フルーツ', 25 children: { 26 banana: { 27 name: 'バナナ', 28 children: {}, 29 }, 30 apple: { 31 name: 'りんご', 32 children: {}, 33 }, 34 mandarin: { 35 name: 'みかん', 36 children: {}, 37 }, 38 } 39 } 40 } 41 } 42 } 43} 44 45console.log(getItem(list, "").name); // リスト 46console.log(getItem(list, "food").name); // 食べ物 47console.log(getItem(list, "food.fruits").name); // フルーツ 48console.log(getItem(list, "food.fruits.apple").name); // りんご 49 50// 洒落た出力がしたければこんなテストも出来る 51console.log(JSON.stringify( 52 ["", "food", "food.fruits", "food.fruits.apple"].map( 53 path => getItem(list, path).name 54 ), null, 2 55)); 56// [ 57// "リスト", 58// "食べ物", 59// "フルーツ", 60// "りんご" 61// ]

【おまけ】 これで良くねという別解

Mapやオブジェクトのキーには別にコロン.等の文字列を含めても構いません。

js

1const list = { 2 "food": "食べ物", 3 "food.fruits": "フルーツ", 4 "food.fruits.apple": "りんご", 5 "food.fruits.banana": "バナナ", 6 "food.fruits.mandarin": "みかん", 7} 8 9console.log(list["food.fruits.apple"]); // りんご 10 11// 子供要素の一覧を検索出来る関数も作ってみた 12const filterChildren = (list, path) => 13 Object.keys(list).filter(key => key.indexOf(path + '.') == 0); 14 15console.log(filterChildren(list, "food.fruits")); 16// ["food.fruits.apple", "food.fruits.banana", "food.fruits.mandarin"]

これで良いじゃんと、代替案も添えて提案するのも出来るエンジニアの仕事の一つです。

投稿2020/02/17 02:33

miyabi-sun

総合スコア21158

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

takopo

2020/02/17 03:20

ご回答ありがとうございます! このような方法があるのですね。 こちらの拙い質問にも関わらず、ここまで詳しくお教えいただいて感動しております。 書いていただいた内容は私にとってはレベルが高すぎてついていけない部分があるのですが、少しずつ読み解いていこうと思います。 大変勉強になりました。ありがとうございました。
miyabi-sun

2020/02/17 03:23

コードは上級者が即納品出来るようなレベルでサラッと書いてます。 なのでちょっと大変かも知れませんね。 まずはfor文で同じ挙動をするようなコードを頑張って書いてみてください。
guest

0

ベストアンサー

そのアクセスの仕方は不可能です
fruitsが文字列なら、文字列からappleプロパティはアクセスできません

投稿2020/02/17 00:26

yambejp

総合スコア114839

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yambejp

2020/02/17 00:29

あえてやるなら、Stringオブジェクトを利用するとか・・・ const food = { fruits:Object.assign(new String('フルーツ'),{ banana: 'バナナ', apple : 'りんご', orange: 'みかん', }), }; console.log(food.fruits); console.log(food.fruits.apple);
takopo

2020/02/17 01:47

ご回答ありがとうございます。 オブジェクトについて間違った認識をしておりました。 書いていただいたコードでうまくアクセスできたのですが、 オブジェクトについてきちんと調べて、他のアクセスの仕方を考えてみたいと思います。
guest

0

可能か不可能かで言ったら可能ですが、推奨できません。オブジェクトならオブジェクト、文字列なら文字列で固めるべきです。
もし私がチームメンバーがこんなコードを書いていたら、二度とその人とは一緒のプロジェクトに入りたくないと思うでしょう。

js

1const food = {fruits: (()=>{ 2 const str = new String('フルーツ'); 3 str.apple = 'りんご'; 4 return str; 5})()}; 6document.write(`<p>${food.fruits}</p>`); 7document.write(`<p>${food.fruits.apple}</p>`);

投稿2020/02/17 00:37

thyda.eiqau

総合スコア2982

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

thyda.eiqau

2020/02/17 01:38

document.writeを使っているのはスマホからCodePenで検証コードを書いていてConsoleが見られなかったからです。document.writeを使うのも推奨できません。
takopo

2020/02/17 01:45

ご回答ありがとうございます。 おっしゃる通り確かに考え方が間違っておりました・・・ ご回答いただいたコードはとても素晴らしくうまくいきましたが、改めてもう一度考え直してみたいと思います。
yambejp

2020/02/17 02:03

codepenにもconsole機能は一応あります。 ただhtmlに表記したほうが確かにわかりやすいと思います。 document.writeするより特定のタグのtextContentを書き換えたほうが より汎用性が高いかもしれません
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問