Mapオブジェクトに関して
どうもフロントエンドエンジニアのoreoです。今回は、JavaScriptでたまに見かけるMap
に関して、改めて整理してみたいと思います。
Mapとは?
Map
は、Object
に似たキーと値をもつデータのコレクションです。Object
とは主に下記のような違いがあります(詳細後述)。
①キーにString
以外を設定することができる
②キーの列挙順が保証されている
③要素数の取得が簡単
④直接的に反復処理が可能
Mapの主なメソッド
-
new Map()
- mapコンストラクターからインスタンス化を行い、
map
オブジェクトを作成できる。
- mapコンストラクターからインスタンス化を行い、
-
map.set(key, value)
-
.set
メソッドの第1引数にキー、第2引数に値をそれぞれ渡して設定することができる。
-
-
map.get(key)
-
.get
メソッドで、引数として渡したキーの値を取得できる。
-
-
map.delete(key)
-
.delete
メソッドで、引数として渡したキーの値を削除できる。
-
-
map.entries()
-
.entries
メソッドで、map
の要素であるキーと値を含んだイテレーター(反復可能オブジェクト)を返す。
-
-
map.size
-
.size
メソッドで、map
の要素数を取得できる。
-
-
map.forEach((val,key)=>{})
-
.forEach
メソッドで、反復処理が実行可能。
-
String
以外を設定することができる
違い① キーにobject
は、キーとして主にString
を使用し(*)、下記のように、String
以外のNumber
やBoolean
を使用すると文字列に変換された上でキーとして設定されます。
(*)Symbol
もキーとして設定可能。
const obj = {
キー名:"string型",
1:"number型",
true:"boolean型"
}
console.log(Object.keys(obj)) // [ '1', 'キー名', 'true' ] と出力
一方、Map
では、プリミティブ型、オブジェクト型、関数などString
以外のあらゆるデータ型をキーとして設定し、取得することができます。
const map = new Map();
//プリミティブ型をキーに設定
map.set('string', 'str'); //Stringのキー
map.set(1, 'num'); //Numberのキー
map.set(true, 'bool'); //Booleanのキー
console.log(map.get('string')); //「str」と出力
console.log(map.get(1)); //「num」と出力
console.log(map.get(true)); //「bool」と出力
//オブジェクト型をキーに設定
const keyObj = {}
map.set(keyObj,'obj');
console.log(map.get(keyObj)); //「obj」と出力
//関数をキーに設定
const keyFunc = function(){};
map.set(keyFunc,'func');
console.log(map.get(keyFunc)); //「func」と出力
違い② キーの列挙順が保証されている
object
では、Object.keys()
を使用した場合など、キーの列挙順は設定された順番に並ぶことが保証されていません。
const obj = {};
obj["Human"] = "hoge";
obj[-1] = "hoge";
obj["1"] = "hoge";
obj["Dog"] = "hoge";
console.log(Object.keys(obj)); //「[ '1', 'Human', '-1', 'Dog' ]」と出力
Map
では、キーの列挙順は設定された順番になることが保証されています。なお、任意のキーを上書きしても、そのキーの順番に変化はありません。
const map = new Map();
map.set(1, "hoge");
map.set(2, "hoge");
map.set(3, "hoge");
console.log(...map.entries()); //「[ 1, 'hoge' ] [ 2, 'hoge' ] [ 3, 'hoge' ]」と出力
map.set(1, "上書き");
console.log(...map.entries()); //「[ 1, '上書き' ] [ 2, 'hoge' ] [ 3, 'hoge' ]」と出力
違い③ 要素数の取得が簡単
object
では、Array
に形成してから.length
メソッドで要素数を取得したりなど、要素数の取得に一手間かかります。
一方で、map
では、.size
メソッドで要素数を簡単に取得することが可能です。
const map = new Map();
map.set(1, "hoge");
map.set(2, "hoge");
map.set(3, "hoge");
console.log(map.size); //「3」と出力
違い④ 直接的に反復処理が可能
object
では、反復処理を行う場合、配列に一度加工してから行うなど、違い④の要素数の取得と同様に、一手間かかります。
一方で、map
は、イテレーターなので、for...of
を用いて反復処理が可能です。また、.forEach
メソッドで、簡単に反復処理ができます。
const map = new Map();
map.set(1, "hoge");
map.set(2, "hoge");
map.set(3, "hoge");
//for...ofで列挙可能
for(const m of map){
console.log(m);
}
//以下のように出力される
//[ 1, 'hoge' ]
//[ 2, 'hoge' ]
//[ 3, 'hoge' ]
//forEachで反復処理が可能
map.forEach((val,key)=>{
console.log(val,key);
})
//以下のように出力される
//hoge 1
//hoge 2
//hoge 3
最後に
積極的に使っていませんでしたが、改めて整理すると便利な機能があって使いやすそうですね。反復処理が直接的に実行できるのは魅力的に思たので競プロなどで使っていきたいです!
Discussion