WeakMap
Baseline Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.
WeakMap
オブジェクトは、キーが弱く参照されるキーと値の組のコレクションです。キーはオブジェクトでなければならず、値は任意の値を取ることができます。
WeakMap
については、 WeakMap オブジェクトのガイド (キー付きコレクション内) でより詳しく解説しています。
解説
なぜ WeakMap なのか?
map API は、4 つの API メソッドから共有される 2 つの配列 (1 つはキー用、もう 1 つは値用) を用いることで、JavaScript で実装できます。このマップに要素を設定すると、それぞれの配列の最後に同時にキーと値を追加することになります。その結果、両方の配列でキーと値のインデックスは対応がとれています。マップから値を取得するには、すべてのキーを操作して一致するものを見つけ、見つかったキーのインデックスを使用して値の配列から対応する値を取り出します。
そうした実装では、主に 2 つの不都合が生じることとなります。
- 第一に、設定や探索の計算量が
O(n)
となること (n はマップ中におけるキーの数) で、どちらの操作も一致する値を見つけるためにキーのリストを反復しなければならないからです。 - 第二の不都合は、配列が各キーと各値への参照を無期限に維持することを保証しているため、メモリリークが発生することです。これらの参照は、オブジェクトへの他の参照がない場合でも、キーがガベージコレクションされるのを防ぎます。これにより、対応する値がガベージコレクションされるのを防ぐことにもなります。
これに対して、ネイティブの WeakMap
では、キーとなるオブジェクトに対しては"弱い"参照が保持されます。これにより、キーとなったオブジェクトへの参照が他に存在しない場合に、そのオブジェクトはガベージコレクションの対象に含まれるようになります。ネイティブの WeakMap はキーとそのキーに関する情報をマッピングする場合に、キーがガベージコレクションされていないときにだけ意味があるため特に有用な構造です。
弱い参照を用いるため、WeakMap
のキーは列挙できません。 キーの一覧を取得するメソッドは存在しません。もし、可能であれば、キーの一覧はガベージコレクションに依存することになり、非決定性が生まれます。キーの一覧が必要な場合は、Map
を使うことになります。
コンストラクター
WeakMap()
-
新しい
WeakMap
オブジェクトを生成します。
インスタンスメソッド
WeakMap.prototype.delete(key)
-
key
に関連した値を削除します。その後WeakMap.prototype.has(key)
はfalse
を返します。 WeakMap.prototype.get(key)
-
key
に関連した値を返します。見つからない場合、undefined
を返します。 WeakMap.prototype.has(key)
-
WeakMap
オブジェクト内にkey
に関連した値があるかどうか示す Boolean を返します。 WeakMap.prototype.set(key, value)
-
WeakMap
オブジェクト内にkey
に対する値を設定し、WeakMap
オブジェクトを返します。
例
WeakMap の使用
const wm1 = new WeakMap(),
wm2 = new WeakMap(),
wm3 = new WeakMap();
const o1 = {},
o2 = function () {},
o3 = window;
wm1.set(o1, 37);
wm1.set(o2, "azerty");
wm2.set(o1, o2); // 値は(オブジェクトまたは関数を含む)何であってもかまいません
wm2.set(o3, undefined);
wm2.set(wm1, wm2); // キーも値もどんなオブジェクトでもかまいません。 WeakMap であってもよいのです!
wm1.get(o2); // "azerty"
wm2.get(o2); // wm2 には o2 に関連付けられた値が無い為、undefined が返ってきます
wm2.get(o3); // 値が undefined と関連付けられている為、undefined が返ってきます
wm1.has(o2); // true
wm2.has(o2); // false
wm2.has(o3); // true (値が関連付けられているならば、たとえ値が 'undefined' であっても true となります)
wm3.set(o1, 37);
wm3.get(o1); // 37
wm1.has(o1); // true
wm1.delete(o1);
wm1.has(o1); // false
.clear() メソッドを持つ WeakMap 風のクラスの実装
class ClearableWeakMap {
constructor(init) {
this._wm = new WeakMap(init);
}
clear() {
this._wm = new WeakMap();
}
delete(k) {
return this._wm.delete(k);
}
get(k) {
return this._wm.get(k);
}
has(k) {
return this._wm.has(k);
}
set(k, v) {
this._wm.set(k, v);
return this;
}
}
仕様書
Specification |
---|
ECMAScript Language Specification # sec-weakmap-objects |
ブラウザーの互換性
BCD tables only load in the browser