Map オブジェクト

Map オブジェクトはキーと値のペアを保存します。任意の値(オブジェクトまたはプリミティブ値)をキーまたは値として使用できます。

Maps と Objects の違い

  • Object のキーは文字列または Symbols のみですが、Map のキーは任意の値にできます。
  • Map のキーと値は順序付けられています(FIFO の原則)が、オブジェクトに追加されたキーは順序付けられていません。
  • Map のキーと値のペアの数は size プロパティから取得できますが、Object のキーと値のペアの数は手動で計算するしかありません。
  • Object はそれぞれ独自のプロトタイプを持ち、プロトタイプチェーン上のキー名が自分でオブジェクトに設定したキー名と衝突する可能性があります。

Map の key

key が文字列の場合

var myMap = new Map(); var keyString = "a string"; myMap.set(keyString, "キー 'a string' に関連付けられた値"); myMap.get(keyString); //"キー 'a string' に関連付けられた値" myMap.get("a string"); //"キー 'a string' に関連付けられた値" //keyString === 'a string' であるため

key がオブジェクトの場合

var myMap = new Map(); var keyObj = {}, myMap.set(keyObj, "キー keyObj に関連付けられた値");  myMap.get(keyObj); //"キー keyObj に関連付けられた値" myMap.get({}); //undefined。keyObj !== {} であるため

key が関数の場合

var myMap = new Map(); var keyFunc = function () {}, //関数 myMap.set(keyFunc, "キー keyFunc に関連付けられた値"); myMap.get(keyFunc); //"キー keyFunc に関連付けられた値" myMap.get(function() {}) //undefined。keyFunc !== function () {} であるため

key が NaN の場合

var myMap = new Map(); myMap.set(NaN, "not a number"); myMap.get(NaN); // "not a number" var otherNaN = Number("foo"); myMap.get(otherNaN); // "not a number"

NaN は任意の値、さらには自分自身とも等しくありませんが(NaN !== NaN は true を返します)、NaN は Map のキーとしては区別されません。

Map の反復

Map を走査するには、以下の2つが最も高レベルです。

for...of

var myMap = new Map(); myMap.set(0, "zero"); myMap.set(1, "one"); //2つのログが表示されます。1つは "0 = zero"、もう1つは "1 = one" です。 for (var [key, value] of myMap) {   console.log(key + " = " + value); } for (var [key, value] of myMap.entries()) { console.log(key + " = " + value); } /*この entries メソッドは、挿入順に Map オブジェクト内の各要素の [key, value] 配列を含む新しい Iterator オブジェクトを返します。*/ //2つのログが表示されます。1つは "0"、もう1つは "1" です。 for (var key of myMap.keys()) {   console.log(key); } /*この keys メソッドは、挿入順に Map オブジェクト内の各要素のキーを含む新しい Iterator オブジェクトを返します。*/ //2つのログが表示されます。1つは "zero"、もう1つは "one" です。 for (var value of myMap.values()) {   console.log(value); } /*この values メソッドは、挿入順に Map オブジェクト内の各要素の値を含む新しい Iterator オブジェクトを返します。*/

forEach()

var myMap = new Map(); myMap.set(0, "zero"); myMap.set(1, "one"); //2つのログが表示されます。1つは "0 = zero"、もう1つは "1 = one" です。 myMap.forEach(function(value, key) { console.log(key + " = " + value); }, myMap)

Map オブジェクトの操作

Map と Array の変換

var kvArray = [["key1", "value1"], ["key2", "value2"]]; //Map コンストラクタは、2次元のキーと値のペア配列を Map オブジェクトに変換できます。 var myMap = new Map(kvArray); //Array.from 関数を使用すると、Map オブジェクトを2次元のキーと値のペア配列に変換できます。 var outArray = Array.from(myMap);

Map のクローン

var myMap1 = new Map([["key1", "value1"], ["key2", "value2"]]); var myMap2 = new Map(myMap1); console.log(original === clone); //false が出力されます。Map オブジェクトのコンストラクタがインスタンスを生成し、反復して新しいオブジェクトを作り出します。

Map のマージ

var first = new Map([[1, 'one'], [2, 'two'], [3, 'three'],]); var second = new Map([[1, 'uno'], [2, 'dos']]); //2つの Map オブジェクトをマージするとき、重複するキーがある場合は後者が前者を上書きします。対応する値は uno、dos、three です。 var merged = new Map([...first, ...second]);

Set オブジェクト

Set オブジェクトは、プリミティブ値であれオブジェクト参照であれ、任意の型の一意な値を格納できます。

Set の特殊な値

Set オブジェクトに格納される値は常に一意であるため、2つの値が厳密に等しいかどうかを判断する必要があります。いくつかの特殊な値は特別に扱う必要があります:

  • +0 と -0 は、格納時の一意性の判断において厳密に等しいため、重複しません;
  • undefined と undefined は厳密に等しいため、重複しません;
  • NaN と NaN は厳密には等しくありませんが、Set には1つしか格納できず、重複しません。

コード

let mySet = new Set(); mySet.add(1); // Set(1) {1} mySet.add(5); // Set(2) {1, 5} mySet.add(5); //Set(2) {1, 5} ここでは値の一意性が示されています mySet.add("some text"); //Set(3) {1, 5, "some text"} ここでは型の多様性が示されています var o = {a: 1, b: 2}; mySet.add(o); mySet.add({a: 1, b: 2}); // Set(5) {1, 5, "some text", {…}, {…}} //ここでは、オブジェクト間で参照が異なり厳密には等しくない場合でも、値が同じであれば Set に格納できることが示されています

型変換

Array

//Array を Set に変換 var mySet = new Set(["value1", "value2", "value3"]); //... 演算子を使用して、Set を Array に変換 var myArray = [...mySet]; String //String を Set に変換 var mySet = new Set('hello');  // Set(4) {"h", "e", "l", "o"} //注:Set の toString メソッドは Set を String に変換できません

Set オブジェクトの用途

配列の重複除去

var mySet = new Set([1, 2, 3, 4, 4]); [...mySet]; // [1, 2, 3, 4]

和集合

var a = new Set([1, 2, 3]); var b = new Set([4, 3, 2]); var union = new Set([...a, ...b]); // {1, 2, 3, 4}

積集合

var a = new Set([1, 2, 3]); var b = new Set([4, 3, 2]); var intersect = new Set([...a].filter(x => b.has(x))); // {2, 3}

差集合

var a = new Set([1, 2, 3]); var b = new Set([4, 3, 2]); var difference = new Set([...a].filter(x => !b.has(x))); // {1}