Weak References Let the Garbage Collector Reclaim Keys When No Other Reference Exists
WeakMap and WeakSet
Learn when and why to use WeakMap and WeakSet: GC-safe object metadata caching, private data patterns, and why neither collection is iterable.
What you'll learn
- Explain how WeakMap holds keys by weak reference
- Use WeakMap to cache computed metadata without memory leaks
- State why WeakMap and WeakSet do not support iteration or size
WeakMap and WeakSet are specialised variants of Map and Set where keys
(for WeakMap) or values (for WeakSet) must be objects, and those references
are held weakly. A weak reference does not prevent the garbage collector from
reclaiming the object; once no other strong reference to the key exists, the
entry is automatically pruned.
WeakMap Basics
const cache = new WeakMap();
function processNode(node) {
if (cache.has(node)) {
return cache.get(node); // return cached result
}
const result = expensiveCompute(node);
cache.set(node, result);
return result;
}
function expensiveCompute(node) {
// imagine heavy work here
return { processed: true, id: node.id };
}
const el = { id: 1 };
console.log(processNode(el)); // computed
console.log(processNode(el)); // cached When el falls out of scope and no other code holds a reference to it, the
WeakMap entry is eligible for collection — no memory leak.
Contrast With a Regular Map
// Memory leak — Map keeps el alive forever
const strongCache = new Map();
function leakyProcess(node) {
if (!strongCache.has(node)) {
strongCache.set(node, { processed: true });
}
return strongCache.get(node);
}
// No leak — WeakMap releases the entry automatically
const weakCache = new WeakMap();
function safeProcess(node) {
if (!weakCache.has(node)) {
weakCache.set(node, { processed: true });
}
return weakCache.get(node);
} WeakSet
WeakSet holds a set of objects weakly. A common pattern is tracking which
objects have already been visited without retaining them:
const visited = new WeakSet();
function visit(obj) {
if (visited.has(obj)) {
console.log("already visited");
return;
}
visited.add(obj);
console.log("visiting", obj.name);
}
const page = { name: "home" };
visit(page); // "visiting home"
visit(page); // "already visited" Why No Iteration or Size
Because the GC can remove entries at any point, exposing .size or iteration
would produce non-deterministic results that differ between JS engines and
even between GC cycles on the same engine. The spec deliberately omits these
features to keep the semantics predictable.
| Feature | Map / Set | WeakMap / WeakSet |
|---|---|---|
| Key type | Any | Objects only |
| .size | Yes | No |
| Iterable | Yes | No |
| GC-safe keys | No | Yes |
| Use case | General lookup | Object metadata cache |
Reach for WeakMap whenever you need to attach private data or cached
computations to objects that you do not own — DOM nodes, class instances from
third-party libraries, request objects in a server framework.
Up Next
Now that you have the building blocks, learn the frequency-counting pattern — the most widely used hash-map technique in coding interviews.
Frequency Counting →