SKU // 74

JavaScript WeakSet

A WeakSet is a special, stripped-down Set for tracking objects. Its one superpower: it does not keep objects alive. When nothing else in the program is using an object, JavaScript can delete it from memory, and it quietly disappears from the WeakSet too.

// First, How Memory Cleanup Works

JavaScript automatically frees memory for objects that nothing refers to anymore. This is called garbage collection:

let user = { name: "Ava" };
user = null;   // nothing points to that object now: it can be cleaned up

A regular Set counts as "something pointing to it." An object inside a Set is never cleaned up while the Set exists:

const seen = new Set();
let user = { name: "Ava" };
seen.add(user);
user = null;   // the Set still holds it: it stays in memory

A WeakSet holds its objects weakly: it does not count. Once the rest of the program lets go, the object can be collected.

"Can be collected" does not mean "is collected right away". The engine cleans up whenever it decides to, which might be a moment later or much later. Your code never sees it happen.

// Using a WeakSet

const visited = new WeakSet();

const pageA = { url: "/home" };
const pageB = { url: "/about" };

visited.add(pageA);

console.log(visited.has(pageA));   // true
console.log(visited.has(pageB));   // false

visited.delete(pageA);
console.log(visited.has(pageA));   // false
true false false

That is the whole toolkit: add, has, and delete.

// The Rules

Set WeakSet
Can holdAny valueObjects only
Keeps items in memoryYesNo
sizeYesNo
Loop over / list contentsYesNo
clear()YesNo
const ws = new WeakSet();
ws.add("hello");   // TypeError: Invalid value used in weak set
TypeError: Invalid value used in weak set
const ws = new WeakSet();

console.log(ws.size);               // there is no size property
for (const x of ws) {}         // TypeError: ws is not iterable
undefined TypeError: ws is not iterable
Why No size or Loop?
Garbage collection happens whenever the engine decides, not at a predictable moment. If a WeakSet could report its size, the answer could change between two lines of your code for no visible reason. So JavaScript simply does not let you ask. You can only ask about a specific object you already have: has(obj).

// When to Use One: Tagging Objects

A WeakSet is perfect for marking objects without changing them and without causing memory leaks. For example, making sure each item is only processed once:

const processed = new WeakSet();

function processOrder(order) {
  if (processed.has(order)) {
    return `Order ${order.id} already done`;
  }
  processed.add(order);
  return `Processing order ${order.id}`;
}

const o = { id: 7 };
console.log(processOrder(o));
console.log(processOrder(o));
Processing order 7 Order 7 already done

When an order object is finished with and discarded, the WeakSet does not hold it back.

// Another Common Use: Tracking Visitors

A WeakSet can record whether each visitor has been seen, with no extra data:

const visited = new WeakSet();

let john = { name: "John" };
const paul = { name: "Paul" };

function visit(person) {
  if (visited.has(person)) return `Welcome back, ${person.name}`;
  visited.add(person);
  return `Hello, ${person.name}`;
}

console.log(visit(john));
console.log(visit(paul));
console.log(visit(john));

john = null;   // John's object can now be cleaned up, WeakSet entry and all
Hello, John Hello, Paul Welcome back, John
W3Schools error
W3Schools' version declares its visitors with const and then writes John = null. That line throws TypeError: Assignment to constant variable. A variable you plan to clear must be declared with let, as above. (Its comment also calls the WeakSet a WeakMap.)

To count visits instead of just recording them, you need to store a number with each object: that is a WeakMap (JS Map WeakMap).

// Should You Use One?

Rule of Thumb
Most of the time, a regular Set is what you want. Reach for a WeakSet only when you are tagging objects you do not own or control the lifetime of, and you never need to list or count them.

// Quick Check

Which value can be added to a WeakSet?

  1. "hello"
  2. 42
  3. { id: 1 }
  4. null
Show answer
C. A WeakSet holds only objects. Adding a primitive throws TypeError: Invalid value used in weak set.

What does this log?

const ws = new WeakSet();
ws.add({});
console.log(ws.size);
Show answer
undefined. WeakSets have no size, because garbage collection could change the count at any moment.

Nothing else refers to an object in a WeakSet anymore. When is it removed?

  1. Immediately
  2. On the next line of code
  3. Whenever the engine runs garbage collection
  4. Never
Show answer
C. It becomes eligible for cleanup, and the engine removes it on its own schedule. That unpredictability is why you cannot count or loop a WeakSet.

// Try It

  1. Click Open Playground and run it. Then add b and check again
  2. Try adding a number or string and read the error
  3. Try ws.size and a for...of loop on a WeakSet. What happens?
  4. Write markRead(message) and isRead(message) using a WeakSet of message objects
// Video Walkthroughs
Last updated: Oct 10, 2026, 1:42 AM ET