WeakMaps
WeakMap是map的一个变种,它们的大多数外部行为是相同的,而在底层内存分配(明确地说是它的GC)如何工作上有区别。
WeakMap(仅)接收对象作为键。这些对象被 弱 持有,这意味着如果对象本身被垃圾回收掉了,那么在WeakMap中的记录也会被移除。这是观察不到的,因为一个对象可以被垃圾回收的唯一方法是不再有指向它的引用 —— 一旦不再有指向它的引用,你就没有对象引用可以用来检查它是否存在于这个WeakMap中。
除此以外,WeakMap的API是相似的,虽然限制更多:
var m = new WeakMap();
var x = { id: 1 },
y = { id: 2 };
m.set( x, "foo" );
m.has( x ); // true
m.has( y ); // false
WeakMap没有size
属性和clear()
方法,它们也不对它们的键,值和记录暴露任何迭代器。所以即便你解除了x
引用,它将会因GC从m
中移除它的记录,也没有办法确定这一事实。你只能相信JavaScript会这么做!
就像map一样,WeakMap让你将信息与一个对象软关联。如果你不能完全控制这个对象,比如DOM元素,它们就特别有用。如果你用做map键的对象可以被删除并且应当在被删除时成为GC的回收对象,那么一个WeakMap就是更合适的选项。
要注意的是WeakMap只弱持有它的 键,而不是它的值。考虑如下代码:
var m = new WeakMap();
var x = { id: 1 },
y = { id: 2 },
z = { id: 3 },
w = { id: 4 };
m.set( x, y );
x = null; // { id: 1 } 是可以GC的
y = null; // 由于 { id: 1 } 是可以GC的,因此 { id: 2 } 也可以
m.set( z, w );
w = null; // { id: 4 } 不可以GC
因此,我认为WeakMap被命名为“WeakKeyMap”更好。