JavaScriptで連想配列を利用する際にObjectではなくMapを使うメリット
はじめに
JavaScriptで値のユニークな配列を利用する方法(Set) のエントリに関連して。
「ES2015」で新たに用意された便利なコレクションオブジェクトとして Map
があります。
他言語だと、例えばJavaのMapのように組み込みの連想配列機能が用意されています。Map
を利用すると、それまでは Object
で代用してきた連想配列機能を実現することができます。
とはいえ今まで Object
で実現できていたのならそれで良いのではないか?という疑問が浮かびました。
そこで Object
ではなく Map
を使う際の違いやメリットを調べてみました。
検証環境
従来のObjectを使った場合の連想配列の作り方
従来のObjectを使っての連想配列の作り方は以下のようなコードになります。
(example1.js)
node
コマンドを使ってコマンドラインから実行した結果は以下のようになります。
Objectを使った場合のキーは暗黙に変換される
Objectを利用した場合には、キーの取扱に注意しなければいけません。
実際にソースコードを見ていきましょう。
以下の例ではObjectに対して、Numberの 2
と Stringの "2"
をキーとして値をセットしています。
(example2.js)
実行すると以下のようになります。
2つの値を別のキーでセットしたにもかかわらず、キーは1つしか保存されていません。
Objectのキーは、自動的に文字列に変換されることがわかります。
別の例を見ていきましょう。
Objectのキーとして、Objectを使ってみます。
(example3.js)
実行すると先程同様、キーは1つしか保存されていません。
先の例と同様で、キーとなる key1
、 key2
それぞれに対して toString
メソッドを呼び出し文字列変換している事がわかります。
いずれの変換結果も [object Object]
ですので、やはり保存されているキーは1つになります。
ちなみに Array
をキーにした場合は、 Array#toString
が格納されている値を列挙しているためにこのような問題は起きないようです。
Objectを使った場合は要素数を確認できない
Objectを使った場合には、これ自体にキーの数を数えるためのメソッドが用意されていません。
ただし、 Object.keys
を使うというちょっとハックな方法をとることで取得することはできました。
直感的ではないですね。
Objectを使った場合は値の一覧を用意に取得できない
やろうと思ったらループ処理を記述する必要があります。
Objectを使った場合はキーの削除方法が「キモチワルイ」
delete
キーワードを利用すれば削除可能ですが、Javaなど他言語の Map
オブジェクトに慣れていると、メソッドで削除するのが直感的ですよね。
Mapを使った場合
ということでMapを使った場合のコードを見ていきます。
MapのキーにNaNを指定した場合の挙動
JavaScriptでは NaN === NaN
は false
となりますが、 NaN
がキーの場合には複数の Nan
キーが発生することはありません。
MapをArrayに変換
ArrayからMap,MapからArrayに変換する方法は以下のとおりです。
Mapでループ処理を行う
Map自体がイテレータなので、 for of
構文でループさせることができます。
実行結果は以下のようになります。
Map
オブジェクト自身が持つ forEach
メソッドを利用することも可能です。
実行結果は以下のようになります。
Mapを使った場合の注意点
注意点があります。
今まで暗黙の文字列変換を行っていたことにより、「数値」でキーを指定しようが「文字列」でキーを指定しようが同じでしたが、これらを明確に区別するようになります。
意識しておかないとバグのもととなります。
ひとこと
特に明確な理由がない場合には Map
オブジェクトを利用して連想配列を実現するのが良いかと思います。
ディスカッション
コメント一覧
まだ、コメントがありません