JavaScript - Map と Set

Map と Set

ES2015 から Map オブジェクトと Set オブジェクトという 2 つの新しいデータ構造が導入されました。Map はオブジェクトと似ており、キーと値の対応関係を作るものです。Set は配列とよく似ていますが、要素の重複は許されません。

Map

Map オブジェクトは単純な key / value です。キーあるいは値として任意の値を使うことができます。

new Map([iterable]);
Map の構文
iterable
要素がキー・値の対(2 要素の配列)である Array または他の反復処理可能なオブジェクトです それぞれのキー・値ペアが新しい Map に追加されます。引数を指定しない場合 (null) は undefined と同じに扱われます。
var map = new Map([["key1", 100]]);
console.log(map.get("key1")); // 100
Map の例

Map オブジェクトのプロパティは以下のとおりです。

Map.length
length プロパティの値は 0 です。
get Map[@@species]
派生クラスを生成するためのコンストラクタ関数です。
Map.prototype
Map コンストラクタのプロトタイプを表します。すべての Map オブジェクトに追加のプロパティを定義できます。

すべての Map インスタンスは Map.prototype を継承します。

Map インスタンスのプロパティは以下のとおりです。

Map.prototype.constructor
インスタンスのプロトタイプを生成する関数を返します。これはデフォルト Map 関数です。
Map.prototype.size
Map オブジェクト内のキー・値ペアの数を返します。
var map = new Map([["key1", 100], ["key2", 200]]);
console.log(map.size); // 2

Map インスタンスのメソッドは以下のとおりです。

Map.prototype.clear()
Map オブジェクトからすべてのキー・値ペアを削除します。
var map = new Map([["key1", 100], ["key2", 200]]);
console.log(map); // Map(2) {"key1" => 100, "key2" => 200}

map.clear();
console.log(map); // Map(0) {}
Map.prototype.delete(key)
key に関連した値を削除し Map.prototype.has(value) が以前返した値を返します。Map.prototype.has(key) はその後 false を返します。
var map = new Map([["key1", 100], ["key2", 200]]);
console.log(map); // Map(2) {"key1" => 100, "key2" => 200}

map.delete("key2");
console.log(map); // Map(1) {"key1" => 100}
Map.prototype.entries()
Map オブジェクト内の要素に対して挿入順に [key, value] の配列を含む新しい Iterator オブジェクトを返します。
var map = new Map();

map.set('0', 'foo');
map.set(1, 'bar');
map.set({}, 'baz');

var mapIter = map.entries();

console.log(mapIter.next().value); // ["0", "foo"]
console.log(mapIter.next().value); // [1, "bar"]
console.log(mapIter.next().value); // [Object, "baz"]
Map.prototype.forEach(callbackFn[, thisArg])
Map オブジェクトに存在するキー・値ペアに対して挿入順に callback 関数を呼び出します。thisArg 引数が forEach に提供された場合 callback に対するこの値として使われます。
function logMapElements(value, key, map) {
    console.log(`[${key}] = ${value}`);
}

new Map([['foo', 3], ['bar', 5]]).forEach(logMapElements);
/* 実行結果
[foo] = 3
[bar] = 5
*/
Map.prototype.get(key)
key に関連した値を返します。存在しない場合 undefined を返します。
var map = new Map();
map.set('bar', 'foo');

map.get('bar');  // foo
map.get('baz');  // undefined
Map.prototype.has(key)
Map オブジェクト内に key に関連した要素が存在するかどうかを示す boolean を返します。
var map = new Map();
map.set('bar', "foo");

map.has('bar');  // returns true
map.has('baz');  // returns false
Map.prototype.keys()
Map オブジェクトの要素に対して挿入順に keys を含む新しい Iterator オブジェクトを返します。
var map = new Map();

map.set("0", "foo");
map.set(1, "bar");
map.set({}, "baz");

var mapIter = map.keys();

console.log(mapIter.next().value); // "0"
console.log(mapIter.next().value); // 1
console.log(mapIter.next().value); // Object
Map.prototype.set(key, value)
Map オブジェクト内に key に対する値を設定します。
var map = new Map();

map.set('0', 'foo');
map.set(1, 'bar');
map.set({}, 'baz');
Map.prototype.values()
Map オブジェクトの要素に対して挿入順に values を含む新しい Iterator オブジェクトを返します。
var map = new Map();

map.set('0', 'foo');
map.set(1, 'bar');
map.set({}, 'baz');

var mapIter = map.values();

console.log(mapIter.next().value); // "foo"
console.log(mapIter.next().value); // "bar"
console.log(mapIter.next().value); // "baz"
Map.prototype[@@iterator]()
Map オブジェクト内の要素に対して挿入順に [key, value] の配列を含む新しい Iterator オブジェクトを返します。
var map = new Map();

map.set("0", "foo");
map.set(1, "bar");
map.set({}, "baz");

var mapIter = map[Symbol.iterator]();

console.log(mapIter.next().value); // ["0", "foo"]
console.log(mapIter.next().value); // [1, "bar"]
console.log(mapIter.next().value); // [Object, "baz"]

WeakMap

WeakMap オブジェクトは Map とよく似ていますが次の点が異なります。

  • キーはオブジェクトでなければならない。
  • キーがガーベッジコレクションの対象になる。
  • イテレーションしたりクリアしたりできない。

WeakMap はオブジェクトのインスタンスに対して、外から操作不可能なプライベートなキーを保管するのに利用することができます。

const SecretHolder = (function() {
    const secrets = new WeakMap();
    return class {
        setSecret(secret) {
            secrets.set(this, secret);
        }
        
        getSecret() {
            return secrets.get(this);
        }
    }
})();

const a = new SecretHolder();
const b = new SecretHolder();

a.setSecret('秘密A');
b.setSecret('秘密B');

console.log(a.getSecret()); // 秘密A
console.log(b.getSecret()); // 秘密B

WeakMap オブジェクトのプロパティは以下のとおりです。

WeakMap.length
length プロパティの値は 0 です。
WeakMap.prototype
WeakMap コンストラクタのプロトタイプを表します。すべての WeakMap オブジェクトに追加のプロパティを定義できます。

すべての WeakMap インスタンスは WeakMap.prototype を継承します。

WeakMap インスタンスのプロパティは以下のとおりです。

WeakMap.prototype.constructor
インスタンスのプロトタイプを生成する関数を返します。これはデフォルト WeakMap 関数です。

WeakMap インスタンスのメソッドは以下のとおりです。

WeakMap.prototype.delete(key)
key に関連した値を削除します。その後 WeakMap.prototype.has(key)false を返します。
var wm = new WeakMap();
wm.set(window, 'foo');

wm.delete(window); // true
wm.has(window);    // false
WeakMap.prototype.delete(key)
key に関連した値を削除します。その後 WeakMap.prototype.has(key)false を返します。
var wm = new WeakMap();
wm.set(window, 'foo');

wm.delete(window); // true
wm.has(window);    // false
WeakMap.prototype.has(key)
WeakMap オブジェクト内に key に関連した値があるかどうか示す Boolean を返します。
var wm = new WeakMap();
wm.set(window, 'foo');

wm.has(window); // true
wm.has('baz');  // false
WeakMap.prototype.set(key, value)
WeakMap オブジェクト内に key に対する値を設定し WeakMap オブジェクトを返します。
var wm = new WeakMap();
var obj = {};

// 要素を追加
wm.set(obj, 'foo');

// 要素を更新
wm.set(obj, 'baz');

Set

Set オブジェクトは、プリミティブ値・オブジェクト参照を問わず、あらゆる型で一意の値を格納できます。

new Set([iterable]);
Set の構文
iterable
イテラブルオブジェクトが渡されたら、そのすべての要素が新しい Set オブジェクトに追加されます。それ以外、もしくは null が渡された場合の Set は空で初期化されます。
var set = new Set(["value1", "value2", "value3"]);
console.log(set); // Set(3) {"value1", "value2", "value3"}
Set の例

Set オブジェクトのプロパティは以下のとおりです。

Set.length
length プロパティの値は 0 です。
get Set[@@species]
派生クラスを生成するためのコンストラクタ関数です。
Set.prototype
Set コンストラクタのプロトタイプを表します。すべての Set オブジェクトに追加のプロパティを定義できます。

すべての Set インスタンスは Set.prototype を継承します。

Set インスタンスのプロパティは以下のとおりです。

Set.prototype.constructor
インスタンスのプロトタイプを生成する関数を返します。これはデフォルト Set 関数です。
Set.prototype.size
Set オブジェクト内の値の数を返します。
var set = new Set();
set.add(1);
set.add(5);
set.add('some text')

set.size; // 3

Set インスタンスのメソッドは以下のとおりです。

Set.prototype.add(value)
引数で与えられた値をもつ新しい要素を Set オブジェクトに追加します。
var set = new Set();

set.add(1);
set.add(5).add("some text"); // chainable

console.log(set); // Set [1, 5, "some text"]
Set.prototype.clear()
すべての要素を Set オブジェクトから取り除きます。
var set = new Set();

set.add(1);
set.add("foo");

set.size;       // 2
set.has("foo"); // true

set.clear();

set.size;       // 0
set.has("bar")  // false
Set.prototype.delete(value)
value に関連した要素を削除します。Set.prototype.has(value) はその後に false を返します。
var set = new Set();
set.add('foo');

set.delete('bar'); // false
set.delete('foo'); // true
Set.prototype.entries()
挿入順に Set オブジェクト内の各要素に対して [value, value] の配列を含む新しい Iterator オブジェクトを返します。そのため、各エントリーは keyvalue が同じ値になります。
var set = new Set();

set.add('foobar');
set.add(1);
set.add('baz');

var setIter = set.entries();

console.log(setIter.next().value); // ["foobar", "foobar"]
console.log(setIter.next().value); // [1, 1]
console.log(setIter.next().value); // ["baz", "baz"]
Set.prototype.forEach(callbackFn[, thisArg])
挿入順に Set オブジェクト内に存在する各値に対して callback 関数を呼びます。thisArg 引数が forEach に渡されたら、各コールバックに対して this 値として使用されます。
function logSetElements(value1, value2, set) {
    console.log("[" + value1 + "] = " + value2);
}

new Set(["foo", "bar", undefined]).forEach(logSetElements);

/* 実行結果
[foo] = foo
[bar] = bar
[undefined] = undefined
*/
Set.prototype.has(value)
Set オブジェクト内に引数で与えられた値をもつ要素が存在するかどうかを示す真偽値を返します。
var set = new Set();
set.add('foo');

set.has('foo');  // true
set.has('bar');  // false
Set.prototype.keys()
挿入順に Set オブジェクト内の各要素に対する値を含む新しい Iterator オブジェクトを返します。
var set = new Set();

set.add('foo');
set.add('bar');
set.add('baz');

var setIter = set.keys();

console.log(setIter.next().value); // foo
console.log(setIter.next().value); // bar
console.log(setIter.next().value); // baz
Set.prototype.values()
挿入順に Set オブジェクト内の各要素に対する values を含む新しい Iterator オブジェクトを返します。
var set = new Set();

set.add('foo');
set.add('bar');
set.add('baz');

var setIter = set.values();

console.log(setIter.next().value); // foo
console.log(setIter.next().value); // bar
console.log(setIter.next().value); // baz
Set.prototype[@@iterator]()
挿入順に Set オブジェクト内の各要素に対する values を含む新しい Iterator オブジェクトを返します。
var set = new Set();

set.add('0');
set.add(1);
set.add({});

var setIter = set[Symbol.iterator]();

console.log(setIter.next().value); // "0"
console.log(setIter.next().value); // 1
console.log(setIter.next().value); // Object

WeakSet

WeakSet オブジェクトはオブジェクトだけを含むことができるセットで、オブジェクトがガーベッジコレクションの対象となる可能性があります。WeakMap 同様、WeakSet の値はイテレーションできません。

var ws = new WeakSet();
var obj = {};

ws.add(obj);
ws.has(obj);    // true

ws.delete(obj);
ws.has(obj);    // false

WeakSet オブジェクトのプロパティは以下のとおりです。

WeakSet.length
length プロパティの値は 0 です。
WeakSet.prototype
WeakSet コンストラクタのプロトタイプを表します。すべての WeakSet オブジェクトに追加のプロパティを定義できます。

すべての WeakSet インスタンスは WeakSet.prototype を継承します。

WeakSet インスタンスのプロパティは以下のとおりです。

WeakSet.prototype.constructor
インスタンスのプロトタイプを生成する関数を返します。これはデフォルト WeakSet 関数です。

WeakSet インスタンスのメソッドは以下のとおりです。

WeakSet.prototype.add(value)
引数で与えられた値をもつ新しい要素を Set オブジェクトに追加します。
var ws = new WeakSet();

ws.add(window); // object
ws.has(window); // true

ws.add(1);      // TypeError
WeakSet.prototype.delete(value)
value に関連した要素を削除します。WeakSet.prototype.has(value) はその後に false を返します。
var ws = new WeakSet();
var obj = {};

ws.add(window);

ws.delete(obj);    // false
ws.delete(window); // true

ws.has(window);    // false
WeakSet.prototype.has(key)
WeakSet オブジェクト内に key に関連した要素が存在するかどうかを示す boolean を返します。
var ws = new WeakSet();
var obj = {};
ws.add(window);

mySet.has(window);  // true
mySet.has(obj);     // false

関連記事

JavaScript のまとめページはプログラミング JavaScript 入門を参照してください。

Category:
プログラミング
公開日:
更新日:
Pageviews:
146
Shares:
2
Tag:
JavaScript