Skip to content

WeakSet

This lesson explains WeakSet with clear examples, use cases, and best practices so you can use modern JavaScript confidently in real projects.

ES6+ WeakSet Overview

WeakSet is an ES6 collection that stores unique objects using weak references. Unlike a regular Set, a WeakSet does not prevent its objects from being garbage collected when no other references to them exist.

WeakSet is useful when you need to track object membership temporarily without causing memory leaks. Common examples include marking DOM nodes as processed, preventing duplicate event handler attachment, and tagging objects for internal library logic.

Feature Description
Introduced In ES6 (ECMAScript 2015)
Stores Objects only
Reference Type Weak references
Main Methods add(), has(), delete()
Iterable No — cannot loop or get size
Common Uses Object tagging, DOM tracking, memory-safe membership

Basic WeakSet Example

const visitedUsers =
  new WeakSet();

const userA = { id: 1, name: "Alex" };
const userB = { id: 2, name: "Sam" };

visitedUsers.add(userA);
visitedUsers.add(userB);

console.log(visitedUsers.has(userA));
console.log(visitedUsers.has(userB));

visitedUsers.delete(userA);

console.log(visitedUsers.has(userA));

A WeakSet works like a Set for checking membership, but it only accepts objects. Use add(), has(), and delete() to manage tracked objects.

How WeakSet Works

When you add an object to a WeakSet, the collection holds a weak reference to that object. If the object is removed from your application and no strong references remain, JavaScript can garbage collect it and automatically remove it from the WeakSet.

Step Description Example Syntax
Create WeakSet Initialize an empty collection. const set = new WeakSet()
Add Object Track an object by reference. set.add(user)
Check Membership See whether the object is tracked. set.has(user)
Remove Object Delete the object from the set. set.delete(user)
Garbage Collection Untracked objects may disappear automatically. No manual cleanup required

WeakSet vs Set

Feature WeakSet Set
Value Types Objects only. Any value, including primitives.
References Weak references. Strong references.
Garbage Collection Entries may be removed automatically. Entries stay until deleted.
Iterable No. Yes.
size Not available. Available.
Best For Temporary object tagging. General unique value storage.

WeakSet Accepts Objects Only

const tags =
  new WeakSet();

const product = {
  id: 101,
  name: "Laptop"
};

tags.add(product);
console.log(tags.has(product));

// This throws a TypeError

// tags.add("laptop");
// tags.add(101);
// tags.add(true);

WeakSet cannot store strings, numbers, booleans, or other primitives. It only works with object references such as plain objects, arrays, functions, and DOM nodes.

Track Processed DOM Nodes

const initializedElements =
  new WeakSet();

function setupTooltip(element) {
  if (initializedElements.has(element)) {
    return;
  }

  element.addEventListener("mouseenter", () => {
    console.log("Show tooltip");
  });

  initializedElements.add(element);
}

const button =
  document.querySelector("#helpButton");

setupTooltip(button);
setupTooltip(button);

WeakSet is ideal for marking DOM elements that already received setup logic. If the element is removed from the page and garbage collected, the WeakSet entry disappears automatically.

Prevent Duplicate Processing

const processedRequests =
  new WeakSet();

function handleRequest(request) {
  if (processedRequests.has(request)) {
    console.log("Already handled.");
    return;
  }

  console.log("Processing request...");
  processedRequests.add(request);
}

const requestA = { url: "/api/users" };
const requestB = { url: "/api/orders" };

handleRequest(requestA);
handleRequest(requestA);
handleRequest(requestB);

Use WeakSet when you need to remember which object instances were already handled without keeping those objects alive longer than necessary.

Tag Objects Internally

const validatedForms =
  new WeakSet();

function validateForm(formObject) {
  if (validatedForms.has(formObject)) {
    return true;
  }

  const isValid =
    formObject.email.includes("@");

  if (isValid) {
    validatedForms.add(formObject);
  }

  return isValid;
}

const signupForm = {
  email: "alex@example.com"
};

console.log(validateForm(signupForm));
console.log(validatedForms.has(signupForm));

Libraries and modules can use WeakSet to attach internal state to objects without modifying the objects themselves or exposing extra properties on them.

Weak References and Garbage Collection

const cache =
  new WeakSet();

function trackTempObject() {
  const temp = { id: Date.now() };
  cache.add(temp);
  return temp;
}

let item = trackTempObject();
console.log(cache.has(item));

item = null;

// Later, when temp has no other references,
// it can be garbage collected and removed
// from the WeakSet automatically

Because WeakSet does not strongly hold objects, it helps avoid memory leaks in long-running applications where temporary object tracking is needed.

WeakSet Methods

Method Description Example
add(value) Adds an object to the WeakSet. set.add(user)
has(value) Returns true if the object exists. set.has(user)
delete(value) Removes an object from the WeakSet. set.delete(user)

WeakSet Limitations

  • Cannot store primitive values such as strings or numbers.
  • Has no size property.
  • Cannot iterate with for...of.
  • No forEach(), keys(), or values() methods.
  • Cannot convert directly to an array.
  • Membership checks only work if you still hold the object reference.

Common WeakSet Use Cases

  • Marking DOM nodes that already have event listeners attached.
  • Preventing duplicate initialization of components or plugins.
  • Tracking temporary object instances during processing.
  • Tagging validated, cached, or authenticated object instances.
  • Internal library bookkeeping without modifying user objects.
  • Memory-safe membership tracking in long-lived applications.

WeakSet Best Practices

  • Use WeakSet only when object membership tracking is enough.
  • Prefer WeakSet over Set when garbage collection matters.
  • Keep a strong reference to an object if you need to check it later.
  • Use regular Set when you need iteration, size, or primitives.
  • Do not expect to list all items stored in a WeakSet.
  • Combine WeakSet with clear object lifecycle management.
  • Document why weak membership tracking is needed in your code.

Common WeakSet Mistakes

  • Trying to store strings, numbers, or booleans in a WeakSet.
  • Expecting to loop through WeakSet contents.
  • Using WeakSet when a Map or Set with iteration is required.
  • Assuming has() works after losing all object references.
  • Using WeakSet for general-purpose unique value storage.
  • Expecting a size property to count stored objects.
  • Choosing WeakSet without understanding garbage collection behavior.

WeakSet vs WeakMap

Feature WeakSet WeakMap
Stores Objects only. Key-value pairs with object keys.
Main Question "Is this object a member?" "What value belongs to this object?"
Methods add(), has(), delete() set(), get(), has(), delete()
Best For Tagging or membership checks. Private metadata attached to objects.

Key Takeaways

  • WeakSet is an ES6 collection for tracking unique object references.
  • It uses weak references, so objects can be garbage collected naturally.
  • Use add(), has(), and delete() to manage membership.
  • WeakSet cannot store primitives and is not iterable.
  • Choose WeakSet for memory-safe object tagging, not general data storage.

Pro Tip

If you only need to know whether an object was seen before, use WeakSet. If you need to store extra data on that object, use WeakMap instead.