WeakSet

new WeakSet([iterable]) | weakset.add(value) | weakset.delete(value) | weakset.has(value)
Returns: WeakSet | boolean · Updated March 13, 2026 · Map and Set
weakset collections memory

A WeakSet is a JavaScript built-in object that stores collections of objects with weak references. Unlike regular Sets, WeakSets only hold object references—they cannot contain primitive values like strings, numbers, or booleans. The key feature of WeakSet is its “weak” hold on stored objects: if an object in the WeakSet has no other references pointing to it, it becomes eligible for garbage collection and will be automatically removed from the WeakSet. This makes WeakSet particularly useful for tracking objects without preventing their memory from being freed, though it also means WeakSets are not enumerable and have no reliable way to count their contents.

Syntax

new WeakSet([iterable])

TypeScript Signatures

interface WeakSet<T extends object = object> {
  constructor(iterable?: Iterable<T>): WeakSet<T>;
  add(value: T): this;
  delete(value: T): boolean;
  has(value: T): boolean;
}

Parameters

ParameterTypeDescription
iterableIterable<object>Optional. An iterable object whose elements will be added to the new WeakSet. Each element must be an object.

Return Value

  • add() returns the WeakSet object (allows chaining)
  • delete() returns true if an element was successfully deleted, false if the element didn’t exist
  • has() returns true if the value exists in the WeakSet, false otherwise

Examples

Creating and Using a WeakSet

const ws = new WeakSet();

const obj1 = { name: "first" };
const obj2 = { name: "second" };

// Add objects to the WeakSet
ws.add(obj1);
ws.add(obj2);

// Check if objects exist
console.log(ws.has(obj1));  // Output: true
console.log(ws.has(obj2));  // Output: true

// Delete an object
ws.delete(obj1);
console.log(ws.has(obj1));  // Output: false
console.log(ws.has(obj2));  // Output: true

WeakSet with Iterable

const obj1 = { id: 1 };
const obj2 = { id: 2 };
const obj3 = { id: 3 };

// Initialize with an iterable (array of objects)
const ws = new WeakSet([obj1, obj2, obj3]);

console.log(ws.has(obj1));  // Output: true
console.log(ws.has(obj2));  // Output: true
console.log(ws.has(obj3));  // Output: true

Memory Management Behavior

const ws = new WeakSet();
let obj = { data: "temporary data" };

ws.add(obj);
console.log(ws.has(obj));  // Output: true

// Remove the only reference to the object
obj = null;

// At this point, the object becomes garbage collectable
// and will be removed from the WeakSet automatically
// (though JavaScript doesn't provide a way to observe this directly)

Common Patterns

Tracking Visited Objects in Recursion

function processObject(obj, visited = new WeakSet()) {
  // Skip if already visited
  if (visited.has(obj)) {
    return;
  }

  // Mark as visited
  visited.add(obj);

  // Process the object
  console.log("Processing:", obj);

  // Recursively process nested objects
  if (typeof obj === "object" && obj !== null) {
    for (const key in obj) {
      processObject(obj[key], visited);
    }
  }
}

const circular = { a: 1 };
circular.self = circular;  // Circular reference

processObject(circular);
// Output: Processing: { a: 1, self: [Circular] }

Temporary Object Tracking

class DOMTracker {
  constructor() {
    this.tracked = new WeakSet();
  }

  track(element) {
    this.tracked.add(element);
    return this;
  }

  isTracked(element) {
    return this.tracked.has(element);
  }

  untrack(element) {
    return this.tracked.delete(element);
  }
}

const tracker = new DOMTracker();

const button = document.createElement("button");
tracker.track(button);

console.log(tracker.isTracked(button));  // Output: true

// When button is removed from DOM and all references are cleared,
// it will be garbage collected automatically

Avoiding Circular References in Data Processing

function deepClone(obj, seen = new WeakSet()) {
  // Handle primitives
  if (typeof obj !== "object" || obj === null) {
    return obj;
  }

  // Detect circular references
  if (seen.has(obj)) {
    return undefined;  // Or handle appropriately
  }

  // Add to seen set
  seen.add(obj);

  // Clone the object
  const cloned = Array.isArray(obj) ? [Global_Objects::eval] : {};
  for (const key in obj) {
    cloned[key] = deepClone(obj[key], seen);
  }

  return cloned;
}

const original = { nested: { value: 42 } };
original.circular = original;

const cloned = deepClone(original);
console.log(cloned.nested.value);  // Output: 42

Next Steps

Now that you understand how WeakSet works, explore how it compares to other collection types and when to use each.

See Also

  • Set — Regular Set collection for storing unique values
  • WeakMap — Similar weak-reference collection for key-value pairs
  • Map — Key-value pairs with strong references
  • set::has — Check membership in a regular Set