WeakSet

The WeakSet object lets you store weakly held objects in a collection.

Description

WeakSet objects are collections of objects. Just as with Sets, each object in a WeakSet may occur only once; all objects in a WeakSet's collection are unique.

The main differences to the Set object are:

  • WeakSets are collections of objects only. They cannot contain arbitrary values of any type, as Sets can.
  • The WeakSet is weak, meaning references to objects in a WeakSet are held weakly. If no other references to an object stored in the WeakSet exist, those objects can be garbage collected.

    Note: This also means that there is no list of current objects stored in the collection. WeakSets are not enumerable.

Use case: Detecting circular references

Functions that call themselves recursively need a way of guarding against circular data structures by tracking which objects have already been processed.

WeakSets are ideal for this purpose:

// Execute a callback on everything stored inside an object
function execRecursively(fn, subject, _refs = null){
  if(!_refs)
    _refs = new WeakSet();

  // Avoid infinite recursion
  if(_refs.has(subject))
    return;

  fn(subject);
  if("object" === typeof subject){
    _refs.add(subject);
    for(let key in subject)
      execRecursively(fn, subject[key], _refs);
  }
}

const foo = {
  foo: "Foo",
  bar: {
    bar: "Bar"
  }
};

foo.bar.baz = foo; // Circular reference!
execRecursively(obj => console.log(obj), foo);

Here, a WeakSet is created on the first run, and passed along with every subsequent function call (using the internal _refs parameter).

The number of objects or their traversal order is immaterial, so a WeakSet is more suitable (and performant) than a Set for tracking object references, especially if a very large number of objects is involved.

Constructor

WeakSet()

Creates a new WeakSet object.

Instance methods

WeakSet.prototype.add(value)

Appends value to the WeakSet object.

WeakSet.prototype.delete(value)

Removes value from the WeakSet. WeakSet.prototype.has(value) will return false afterwards.

WeakSet.prototype.has(value)

Returns a boolean asserting whether value is present in the WeakSet object or not.

Examples

Using the WeakSet object

const ws = new WeakSet();
const foo = {};
const bar = {};

ws.add(foo);
ws.add(bar);

ws.has(foo);    // true
ws.has(bar);    // true

ws.delete(foo); // removes foo from the set
ws.has(foo);    // false, foo has been removed
ws.has(bar);    // true, bar is retained

Note that foo !== bar. While they are similar objects, they are not the same object. And so they are both added to the set.

Specifications

Specification
ECMAScript Language Specification
# sec-weakset-objects

Browser compatibility

BCD tables only load in the browser

See also