WeakMap オブジェクトは、キーが弱く参照されるキーと値の組のコレクションです。キーはオブジェクトでなければならず、値は任意の値を取ることができます。
WeakMap については、 WeakMap object in キー付きコレクション の節でより詳しく解説しています。
構文
new WeakMap([iterable])
引数
iterable- 要素がキー・値の組 (2 要素の配列) である配列または他の反復処理可能なオブジェクトです。それぞれのキー・値の組が新しい WeakMap に追加されます。 null は undefined として扱われます。
解説
WeakMap のキーは Object に限ります。プリミティブ型 はキーとして使えません(例えば Symbol は WeakMap のキーとして使えません)。
なぜ WeakMap なのか?
map API は、4 つの API メソッドから共有される 2 つの配列 (1 つはキー用、もう 1 つは値用) を用いることで、JavaScript で実装できます。このマップに要素を設定すると、それぞれの配列の最後に同時にキーと値を追加することになります。その結果、両方の配列でキーと値のインデックスは対応がとれています。マップから値を取得するには、すべてのキーを操作して一致するものを見つけ、見つかったキーのインデックスを使用して値の配列から対応する値を取り出します。
そうした実装では、主に 2 つの不都合が生じることとなります。1 つ目の不都合は、探索の計算量が O(n) となること (O(n) search) (n はマップ中におけるキーの数を表す)。もう 1 つの不都合はメモリーリークの問題です。 (2 つの配列を使って) マップを自作した場合、キーの配列はキーとしたオブジェクトへの参照を保持し続けるでしょう。従って、それらのキーとなったオブジェクトはガベージコレクションの対象から外されることとなります。
ネイティブな WeakMap では、キーとなるオブジェクトに対しては"弱い"参照が保持されます。これにより、キーとなったオブジェクトへの参照が他に存在しない場合に、そのオブジェクトはガベージコレクションの対象に含まれるようになります。ネイティブな WeakMap はキーとそのキーに関する情報をマッピングする場合に、キーがガベージコレクションされていないときにだけ意味があるため特に有用な構造です。
弱参照を用いるため、WeakMap のキーは列挙できません (つまり、キーの一覧を取得するメソッドは存在しません)。もし、可能であれば、キーの一覧はガベージコレクションに依存することになり、非決定性が生まれます。キーの一覧が必要な場合は、Mapを使うことになります。
プロパティ
WeakMap.lengthlengthプロパティの値は0です。WeakMap.prototypeWeakMapコンストラクターのプロトタイプを表します。どのWeakMapオブジェクトも、プロパティを追加することが許可されています。
WeakMap インスタンス
すべての WeakMap インスタンスは、WeakMap.prototype から継承します。
プロパティ
WeakMap.prototype.constructor- インスタンスのプロトタイプを生成する関数を返します。これは、デフォルトでは
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.prototype.clear()WeakMapオブジェクトからすべてのキー/バリューペアを削除します。.clear()メソッドを持っていないWeakMapオブジェクトをカプセル化することによって、.clear()メソッドを持つWeakMapオブジェクトに似たオブジェクトを実装することが可能であることに注意してください。(WeakMapページの例を確認してください。)
例
WeakMap を使う
var wm1 = new WeakMap(),
wm2 = new WeakMap(),
wm3 = new WeakMap();
var 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
}
}
仕様書
| 仕様書 | 状態 | 備考 |
|---|---|---|
| ECMAScript (ECMA-262) WeakMap の定義 |
現行の標準 | |
| ECMAScript 2015 (6th Edition, ECMA-262) WeakMap の定義 |
標準 | 初回定義 |
ブラウザーの互換性
| デスクトップ | モバイル | サーバー | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
WeakMap | Chrome 完全対応 36 | Edge 完全対応 12 | Firefox 完全対応 6 | IE 完全対応 11 | Opera 完全対応 23 | Safari 完全対応 8 | WebView Android 完全対応 37 | Chrome Android 完全対応 36 | Firefox Android 完全対応 6 | Opera Android 完全対応 24 | Safari iOS 完全対応 8 | Samsung Internet Android 完全対応 3.0 | nodejs
完全対応
0.12
|
WeakMap() constructor | Chrome 完全対応 36 | Edge 完全対応 12 | Firefox 完全対応 6 | IE 完全対応 11 | Opera 完全対応 23 | Safari 完全対応 8 | WebView Android 完全対応 37 | Chrome Android 完全対応 36 | Firefox Android 完全対応 6 | Opera Android 完全対応 24 | Safari iOS 完全対応 8 | Samsung Internet Android 完全対応 3.0 | nodejs
完全対応
0.12
|
clear | Chrome 未対応 36 — 43 | Edge 未対応 なし | Firefox 未対応 20 — 46 | IE 完全対応 11 | Opera 未対応 25 — 30 | Safari 未対応 8 — 9 | WebView Android 未対応 37 — 43 | Chrome Android 未対応 36 — 43 | Firefox Android 未対応 20 — 46 | Opera Android 未対応 25 — 30 | Safari iOS 未対応 8 — 9 | Samsung Internet Android 未対応 3.0 — 4.0 | nodejs 未対応 0.12 — 4.0.0 |
delete | Chrome 完全対応 36 | Edge 完全対応 12 | Firefox
完全対応
6
| IE 完全対応 11 | Opera 完全対応 23 | Safari 完全対応 8 | WebView Android 完全対応 37 | Chrome Android 完全対応 36 | Firefox Android
完全対応
6
| Opera Android 完全対応 24 | Safari iOS 完全対応 8 | Samsung Internet Android 完全対応 3.0 | nodejs
完全対応
0.12
|
get | Chrome 完全対応 36 | Edge 完全対応 12 | Firefox
完全対応
6
| IE 完全対応 11 | Opera 完全対応 23 | Safari 完全対応 8 | WebView Android 完全対応 37 | Chrome Android 完全対応 36 | Firefox Android
完全対応
6
| Opera Android 完全対応 24 | Safari iOS 完全対応 8 | Samsung Internet Android 完全対応 3.0 | nodejs
完全対応
0.12
|
has | Chrome 完全対応 36 | Edge 完全対応 12 | Firefox
完全対応
6
| IE 完全対応 11 | Opera 完全対応 23 | Safari 完全対応 8 | WebView Android 完全対応 37 | Chrome Android 完全対応 36 | Firefox Android
完全対応
6
| Opera Android 完全対応 24 | Safari iOS 完全対応 8 | Samsung Internet Android 完全対応 3.0 | nodejs
完全対応
0.12
|
set | Chrome 完全対応 36 | Edge 完全対応 12 | Firefox
完全対応
6
| IE
部分対応
11
| Opera 完全対応 23 | Safari 完全対応 8 | WebView Android 完全対応 37 | Chrome Android 完全対応 36 | Firefox Android
完全対応
6
| Opera Android 完全対応 24 | Safari iOS 完全対応 8 | Samsung Internet Android 完全対応 3.0 | nodejs
完全対応
0.12
|
凡例
- 完全対応
- 完全対応
- 部分対応
- 部分対応
- 未対応
- 未対応
- 非標準。ブラウザー間の互換性が低い可能性があります。
- 非標準。ブラウザー間の互換性が低い可能性があります。
- 非推奨。新しいウェブサイトでは使用しないでください。
- 非推奨。新しいウェブサイトでは使用しないでください。
- 実装ノートを参照してください。
- 実装ノートを参照してください。
- ユーザーが明示的にこの機能を有効にしなければなりません。
- ユーザーが明示的にこの機能を有効にしなければなりません。