WeakMaps

WeakMaps are a variation on maps, which has most of the same external behavior but differs underneath in how the memory allocation (specifically its GC) works.

WeakMaps take (only) objects as keys. Those objects are held weakly, which means if the object itself is GC’d, the entry in the WeakMap is also removed. This isn’t observable behavior, though, as the only way an object can be GC’d is if there’s no more references to it — once there are no more references to it, you have no object reference to check if it exists in the WeakMap.

Otherwise, the API for WeakMap is similar, though more limited:

  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

WeakMaps do not have a size property or clear() method, nor do they expose any iterators over their keys, values, or entries. So even if you unset the x reference, which will remove its entry from m upon GC, there is no way to tell. You’ll just have to take JavaScript’s word for it!

Just like Maps, WeakMaps let you soft-associate information with an object. But they are particularly useful if the object is not one you completely control, such as a DOM element. If the object you’re using as a map key can be deleted and should be GC-eligible when it is, then a WeakMap is a more appropriate option.

It’s important to note that a WeakMap only holds its keys weakly, not its values. Consider:

  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 } is GC-eligible
  8. y = null; // { id: 2 } is GC-eligible
  9. // only because { id: 1 } is
  10. m.set( z, w );
  11. w = null; // { id: 4 } is not GC-eligible

For this reason, WeakMaps are in my opinion better named “WeakKeyMaps.”