By the end, you can use a JavaScript WeakSet to mark objects as seen or owned without keeping them alive in memory.
What it is
A WeakSet is a collection of objects whose references are weak. If an object is only referenced by the WeakSet, the JavaScript engine may garbage-collect it and remove it from the set. Unlike Set, a WeakSet cannot contain primitives, cannot be iterated, and has no size property.
Mental model: a private guest list for objects. It answers “have I seen this object?” but does not force the object to stay in memory.
Related terms: Set, WeakMap, garbage collection, object identity.
Why it matters
- Track processed objects without creating memory leaks.
- Mark DOM nodes or class instances as initialized.
- Implement private state or “seen” flags keyed by object identity.
- Reduce accidental retention when caches are temporary.
Syntax or steps
- Create a WeakSet:
const seen = new WeakSet(); - Add an object:
seen.add(obj); - Check membership:
seen.has(obj); - Remove an object:
seen.delete(obj);
add returns the WeakSet, while has and delete return booleans.
Example
const processed = new WeakSet();
function handle(node) {
if (processed.has(node)) {
console.log("Already handled");
return;
}
processed.add(node);
console.log("Handling node");
}
const a = { id: 1 };
const b = { id: 2 };
handle(a);
handle(a);
handle(b);
console.log(processed.has(a)); // true
console.log(processed.has(b)); // true
Part by part: processed stores only objects that have already been handled. The first call to handle(a) adds a and logs “Handling node”. The second call finds a already present and logs “Already handled”. The call with b is independent because b is a different object reference.
Common mistakes
- Adding primitives:
ws.add(42)throws aTypeError. Fix: use a normalSetor wrap the value in an object. - Expecting iteration or size: WeakSet has no
forEach,size, or spread support. Fix: useSetwhen you need enumeration. - Assuming immediate deletion: garbage collection timing is not guaranteed. Fix: use WeakSet for optional cleanup, not deterministic resource release.
- Confusing it with WeakMap: WeakSet stores objects as members; WeakMap stores key-value pairs. Fix: choose WeakMap when you need associated data.
When to use it
Use WeakSet when you need membership by object identity and want to avoid retaining objects. Use Set when you need iteration, size, or primitives. Use WeakMap when you need to attach data to objects without retaining them.
| Need | Use | Why |
|---|---|---|
| Iterate all items | Set |
WeakSet cannot be enumerated. |
| Store primitives | Set |
WeakSet only accepts objects. |
| Track objects without leaks | WeakSet |
Entries disappear when objects are unreachable. |
| Attach metadata to objects | WeakMap |
It maps weak keys to values. |
Practice
Guided exercise: create a WeakSet, add two objects, check both, delete one, then check again.
const marks = new WeakSet();
const x = {};
const y = {};
marks.add(x);
marks.add(y);
console.log(marks.has(x), marks.has(y)); // true true
marks.delete(x);
console.log(marks.has(x), marks.has(y)); // false true
Challenge: write ensureOnce(obj) so it logs “first time” only once per object. Hint: use has to check and add to record.
Quick check
Question: Can a WeakSet keep an object alive?
Answer: No. Its references are weak; if no other references exist, the object can be garbage-collected.
Summary
WeakSet is a lightweight membership tracker for objects. It trades enumeration and size for memory safety. Use it when object identity matters and accidental retention would be harmful.