読者です 読者をやめる 読者になる 読者になる

JS.next

JavaScriptの最新実装情報を追うブログ

Weak Collectionsがデフォルトで有効になった

概要

ES2015で導入される機能である、Promise、WeakMap、WeakSetコンストラクタがデフォルトで有効になった。


Weak Collectionsについて

なぜ必要なのか

ES2015ではキーにオブジェクトも含む様々な型の値をとれる連想配列が導入された。
それらはCollectionsと呼ばれ、Map、Setコンストラクタとして提供される。

ここで、Mapの一部機能を自作してみると、

function MyMap() {
  this._keyTable = []
  this._valTable = []
}

MyMap.prototype.set = function (key, val) {
  this._keyTable.push(key)
  this._valTable.push(val)
}

MyMap.prototype.get = function (key) {
  var index = this._keyTable.indexOf(key)
  return this._valTable[index]
}

このようになり、使うときは、

keyObj = {}

mm = new MyMap
mm.set(keyObj, 123)
mm.get(keyObj)  // 123

このようになる。
しかしこのようなMap実装には1つ欠点がある。
それは、他のkeyObjへの参照が全て無くなっても、mmインスタンスがkeyObjとそれに紐付けられた値をいつまでも保持するので、メモリリークの原因になってしまうということである。

単純な話、以下のようなコードですぐにメモリが枯渇してしまう。

while (true) mm.set({}, 123)

そこで登場するのがWeak CollectionsであるWeakMap、WeakSetであり、これらはkeyに取ったオブジェクトを弱参照で保持する。
つまり、他でそのオブジェクトが参照されなくなった時きちんとGCされ、valueを開放することができる。


API概略

作る
wm = new WeakMap
ws = new WeakSet


加える
wm.set(keyObj, val)
ws.add(keyObj)


調べる
wm.has(keyObj)  // true
ws.has(keyObj)  // true


取り出す
wm.get(keyObj)  // val


消す
wm.delete(keyObj)  // true
ws.delete(keyObj)  // true


初期化する

WeakでないCollectionsと違ってclearメソッドによる初期化はできない。


デフォルトで有効になるバージョン

V8 (3.25.x) 3.26.31.8 3.31.14(-clear)
Chrome M36
Node 0.11.13


外部参考リンク