WeakMaps

WeakMap是map的一个变种,它们的大多数外部行为是相同的,而在底层内存分配(明确地说是它的GC)如何工作上有区别。

WeakMap(仅)接收对象作为键。这些对象被 持有,这意味着如果对象本身被垃圾回收掉了,那么在WeakMap中的记录也会被移除。这是观察不到的,因为一个对象可以被垃圾回收的唯一方法是不再有指向它的引用 —— 一旦不再有指向它的引用,你就没有对象引用可以用来检查它是否存在于这个WeakMap中。

除此以外,WeakMap的API是相似的,虽然限制更多:

  1. var m = new WeakMap();
  2. var x = { id: 1 },
  3. y = { id: 2 };
  4. m.set( x, "foo" );
  5. m.has( x ); // true
  6. m.has( y ); // false

WeakMap没有size属性和clear()方法,它们也不对它们的键,值和记录暴露任何迭代器。所以即便你解除了x引用,它将会因GC从m中移除它的记录,也没有办法确定这一事实。你只能相信JavaScript会这么做!

就像map一样,WeakMap让你将信息与一个对象软关联。如果你不能完全控制这个对象,比如DOM元素,它们就特别有用。如果你用做map键的对象可以被删除并且应当在被删除时成为GC的回收对象,那么一个WeakMap就是更合适的选项。

要注意的是WeakMap只弱持有它的 ,而不是它的值。考虑如下代码:

  1. var m = new WeakMap();
  2. var x = { id: 1 },
  3. y = { id: 2 },
  4. z = { id: 3 },
  5. w = { id: 4 };
  6. m.set( x, y );
  7. x = null; // { id: 1 } 是可以GC的
  8. y = null; // 由于 { id: 1 } 是可以GC的,因此 { id: 2 } 也可以
  9. m.set( z, w );
  10. w = null; // { id: 4 } 不可以GC

因此,我认为WeakMap被命名为“WeakKeyMap”更好。