🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
JavaScript

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

Q&A

解決済

3回答

2181閲覧

javascriptで添字付きでオブジェクト(配列)をpushする方法

pegy

総合スコア245

JavaScript

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

0グッド

0クリップ

投稿2019/10/19 12:44

以下のようにk1,c1,k2,c3の要素をmarkerDateオブジェクト(配列)にarray.pushにより追加しております。
その結果当然ですが、console.log(markerDate);は以下の通りです。
[0:{
lat:35.639014,
lng:139.638741,
icon:"./z_icon/1_k.png"
}
1:{
lat:35.631350,
lng:139.646900,
icon:"./z_icon/1_c.png"
}
以下省略
]

これを添字付きpushして以下のようにオブジェクトの中にオブジェクトのようにしたいのですが、javascriptでそのようなことは可能でしょうか。
どなたか、お力添えをいただけると大変嬉しいです。
よろしくお願い申し上げます。

[k1:{
lat:35.639014,
lng:139.638741,
icon:"./z_icon/1_k.png"
}
c1:{
lat:35.631350,
lng:139.646900,
icon:"./z_icon/1_c.png"
}
以下省略
]

javascript

1var markerDate =[]; 2 3var k1={ 4 lat:35.639014, 5 lng:139.638741, 6 icon:"./z_icon/1_k.png" 7}; 8markerDate.push(k1) 9 10var c1= 11{ 12 lat:35.631350, 13 lng:139.646900, 14 icon:"./z_icon/1_c.png" 15}; 16 17markerDate.push(c1) 18var k2= 19[ 20 { 21 lat:35.562416, 22 lng:139.614346, 23 icon:"./z_icon/2_k.png" 24 }, 25 { 26 lat:35.757992, 27 lng:139.827880, 28 icon:"./z_icon/2_k.png" 29 } 30]; 31markerDate.push(k2) 32 33var c3= 34{ 35 lat:35.591418, 36 lng:139.546924, 37 icon:"./z_icon/3_c.png" 38}; 39markerDate.push(c3); 40 41console.log(markerDate);

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

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

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

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

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

guest

回答3

0

ベストアンサー

new Map

[] で定義される配列は整数値以外のキーを持てません。
JavaScriptに連想配列はありませんが、近い機能に new Map があります。

JavaScriptに連想配列はありませんが、近いのは

1const map = new Map; 2 3map.set('k1', {lat:35.639014, lng:139.638741, icon:'./z_icon/1_k.png'}); 4console.log(map.get('k1')); // {lat: 35.639014, lng: 139.638741, icon: "./z_icon/1_k.png"}

コードの選択基準

上記のraccy様へのコメントバックにも記載させていただいたのですが、全部をループしたい一方で特定のオブジェクト(配列)にもアクセスしたと言う二つの目的を達成したい場合、javascriptにおいてはこのようなmapクラスでデータを保管することが一般的なのでしょうか?

「一般的」については回答しかねます。
判断基準があいまいですし、固定観念は視野を狭くするので、出来るだけ排除するようにしています。

私は次の流れで実装法を決定します。

  1. 要求仕様に合う実装法をリストアップ
  2. 各々の性質を調査→把握する
  3. その中から最善を選び取る

今回のケースでは、Object.create(null) が候補に上がります。

※これらの作業は @pegy さんの役目だと思っています。
他人に選択権を委ねないように注意してください。
性質把握と選択を繰り返せば、「自分だけの基準」が出来ていくものです。

Re: pegy さん

投稿2019/10/19 13:47

編集2019/10/20 01:15
think49

総合スコア18189

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

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

pegy

2019/10/19 22:21

夜分にコメントをいただき誠にありがとうございます。 Mapを利用することで実装することができました。上記のraccy様へのコメントバックにも記載させていただいたのですが、全部をループしたい一方で特定のオブジェクト(配列)にもアクセスしたと言う二つの目的を達成したい場合、javascriptにおいてはこのようなmapクラスでデータを保管することが一般的なのでしょうか?、そもそもの目的を明確に記載すべきだった点をお詫び申し上げます。 よろしくお願い申し上げます。
think49

2019/10/20 01:15

親記事に追記しました。
pegy

2019/10/21 15:48

コメント遅くなり申し訳ございません。 性質を知るべく、1日かけてじっくり、オブジェクト初期化子Object.create(null)、Map、WeakMapの内容を読んでいました。もちろんまだ理解できていない部分もあるのですが、学んでいく中で普段使用しているPHPの連想配列とJavaScriptのオブジェクトの扱いを同じようにできると錯覚してしまっていること自体が適切ではないことに気がつかされました。そこで学んでいくうちに以下のようにして扱えることがわかりました。またループに関してはObjectKey()を使っていますが、forin+hasownproperty等で対応できることも知りました。 何れにしても、結果的に基本的な書き方を知ることと動作させることができたのですが、ご教示いただいたmapなどによりさらにスマートに記載することやオブジェクトを扱うこともできると思いますので、さらに吟味して、採用すべきものを自分の基準で選べるようにしていきたいと思います。(諸々選択肢を教えていただきましたが、私には難易度が高かったため、少しずつ咀嚼していくうちに、基本的なことがわかった段階にきました、ということになります、冗長なご説明で申し訳ございません) markerDate={} markerDate.k1=[ {    lat:35.639014,    lng:139.638741,    icon:"./z_icon/1k.png",    } ]; markerDate.c1=[ { lat:35.631350, lng:139.646900, icon:"./z_icon/1c.png", } ]; mObj.k2=[ { lat:35.562416, lng:139.614346, icon:"./z_icon/2k.png", },{ lat:35.757992, lng:139.827880, icon:"./z_icon/2k.png", } ]; markerDate.c3=[ { lat:35.591418, lng:139.546924, icon:"./z_icon/3c.png", } ]; var mObjKeys=Object.keys(markerDate); var keyLen=mObjKeys.length; //ループさせたい時 for(i=0, i < keyLen;i++){ markerDate[mObjKeys[i]]//do something } //指定したい時 markerDate["k2"][0]//do something
think49

2019/10/22 00:27 編集

着実に一歩ずつ前進していることが分かる素晴らしいコメントでした。 このように、理解した範囲をまとめて頂けると、回答した甲斐がありますし、追加質問があったとしても要所をおさえた回答ができます。 (逆に理解度が不明だと、回答の方向性が定まらなくなり、ざっくりと広範囲を説明することになりがちです) 記載されたコードは、特定のプロパティ(__proto__等)さえ使用しなければ、問題なく動作します。 (var なしで変数宣言している為に「暗黙のグローバル変数化」しているのは少々気になりますが…。暗黙のグローバル変数は Strict Mode では禁止されます。) https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/var#Implicit_globals_and_outer_function_scope https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Strict_mode#%E3%83%9F%E3%82%B9%E3%81%8B%E3%82%89%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%B8%E3%81%AE%E5%A4%89%E6%8F%9B お疲れ様でした。
guest

0

極めて邪道ですが、Array(配列)もObjectと同じように扱う事はできます。ただし、下記を実行すればわかるようにmarkerDate.lengthは0のままだったり、色々と問題があります。

JavaScript

1var markerDate =[]; 2 3var k1={ 4 lat:35.639014, 5 lng:139.638741, 6 icon:"./z_icon/1_k.png" 7}; 8markerDate['k1'] = k1; 9 10var c1= 11{ 12 lat:35.631350, 13 lng:139.646900, 14 icon:"./z_icon/1_c.png" 15}; 16 17markerDate['c1'] = c1; 18var k2= 19[ 20 { 21 lat:35.562416, 22 lng:139.614346, 23 icon:"./z_icon/2_k.png" 24 }, 25 { 26 lat:35.757992, 27 lng:139.827880, 28 icon:"./z_icon/2_k.png" 29 } 30]; 31markerDate['k2'] = k2; 32 33var c3= 34{ 35 lat:35.591418, 36 lng:139.546924, 37 icon:"./z_icon/3_c.png" 38}; 39markerDate['c3'] = c3; 40 41console.log(markerDate); 42console.log(markerDate.length);

【解説】

Arrayもオブジェクト(object)の一つであり、Objectを継承しています([] instanceof Objectがtureであるということ)。ただし、ちょっと特殊な動作を行うエキゾティックオブジェクト(exotic object)というものです。この特殊な動作とはlengthプロパティと0から2^31-2のプロパティが連動する等の一連の動作です。その特殊な動作を除けば他のオブジェクトと同じように扱う事ができます。つまり、Objectのように任意の名前のプロパティを設定できると言うことです。

ただ、このような方法で追加した要素にはmarkerData['k1']のようにオブジェクトのプロパティとしてアクセスすることはできますが、Array特有のメソッド、ループ、スプレッド演算子等は一切考慮してくれません。例えば、forEach等を使っても、この方法で入れた各要素を見に行ってくれないと言うことです。

ということで、任意の名前の付いた配列、いわゆる連想配列を使いたい場合は、think49さんの回答のとおり、Mapを使うことをお勧めします。古いJavaScriptの参考書には連想配列にはObjectを使うと書いてあることがありますが、問題が起きる場合がありますので、キーが固定でない限りお勧めはしません。

投稿2019/10/19 14:36

raccy

総合スコア21737

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

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

pegy

2019/10/19 22:18

夜分にもかかわらず、コメントをいただきありがとうございます 今回、オブジェクトの構造として達成したい目的は以下の2つなのです。 1.すべてをforでもforeachでも良いのでループして処理させたい 2.特定の添字のオブジェクトに対してアクセスしたい場合がある(これをすべてループして探すのは合理的ではない) そのために、データをどのような構造で持たせようかを悩んでいるのですが、そのような目的においては一般的にMapクラスを利用して値を保管するのでしょうか? 入口の部分で目的を明確に記載すべきところを申し訳ございませんが、よろしくお願い申し上げます。
guest

0

スミマセン、ブラウザで改めで実行したら0とか付きますね。
この回答は一旦無視して下さい。
[0:{
k1:{
(略)
},
1:{
c2:{

js

1markerDate.push({ k1 })

こんな感じでオブジェクトとしてPushしていけば
オブジェクトの配列となります。

json

1[ { k1: { lat: 35.639014, lng: 139.638741, icon: './z_icon/1_k.png' } },2 { c1: { lat: 35.63135, lng: 139.6469, icon: './z_icon/1_c.png' } },3 { k2: [ [Object], [Object] ] },4 { c3: { lat: 35.591418, lng: 139.546924, icon: './z_icon/3_c.png' } } ]

投稿2019/10/19 12:52

編集2019/10/19 14:04
oikashinoa

総合スコア2826

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

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

pegy

2019/10/19 13:48

コメントありがとうございます。 夜分にもかかわらず、誠にありがとうございます。そのようなオブジェクトの格納の仕方があるのですね、 さて実際動作させたところ以下のような構造になりました。 [0:{ k1:{ lat:35.639014, lng:139.638741, icon:"./z_icon/1_k.png" } }, 1:{ c2:{ lat:35.631350, lng:139.646900, icon:"./z_icon/1_c.png" }; } --以下省略-- これについて実際には、以下のような構造にしたいのですがarray.push以外の方法になりますでしょうか? [k1:{ lat:35.639014, lng:139.638741, icon:"./z_icon/1_k.png" } }, c2:{ lat:35.631350, lng:139.646900, icon:"./z_icon/1_c.png" } --以下省略-- 重ねて申し訳ございませんが、よろしくお願い申し上げます。
oikashinoa

2019/10/19 14:41

think49さんが書かれているように配列のキーとして数字が付いてしまいます。 think49さんのMapでの処理ならSetした順も保証されるのでMapの方法が良いと思います。
pegy

2019/10/19 22:13

了解しました、私の質問が不明瞭で誠に申し訳ございません。 よろしくお願い申し上げます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問