Q115: WeakMap, WeakSet and Weak References
What Interviewers Want To Evaluate
This question checks whether you understand weak collections and memory-sensitive data structures. Interviewers want WeakMap, WeakSet, object-only keys, garbage collection behavior, private metadata, cache design, listener tracking, and the limits of weak references.
Senior answers should connect weak collections to memory leaks and avoid overstating control over garbage collection.
Short Interview Answer
WeakMap stores key-value pairs where keys must be objects and are held weakly. If nothing else references a key object, the key and its associated value can be garbage collected. WeakSet stores weakly held objects. These collections are not iterable because their contents depend on garbage collection. They are useful for private metadata, object-associated caches, and tracking objects without preventing cleanup.
Detailed Interview Answer
Normal maps hold strong references to their keys and values.
const map = new Map();
const user = { id: "u1" };
map.set(user, { lastSeen: Date.now() });
As long as map exists, the user object cannot be collected because the map strongly references it.
WeakMap changes the key reference behavior.
const metadata = new WeakMap();
function attachMetadata(object, value) {
metadata.set(object, value);
}
If the object key becomes unreachable elsewhere, the entry can disappear.
WeakMap Keys
WeakMap keys must be objects.
const weakMap = new WeakMap();
weakMap.set({}, "ok");
Primitive keys are not allowed.
weakMap.set("id", "not ok"); // TypeError
This object-only rule exists because weak references depend on object garbage collection.
WeakSet
WeakSet stores objects weakly.
const seen = new WeakSet();
function visit(node) {
if (seen.has(node)) {
return;
}
seen.add(node);
}
This can track visited objects without keeping them alive forever.
Not Iterable
WeakMap and WeakSet are not iterable.
You cannot do this:
for (const entry of weakMap) {
console.log(entry);
}
The reason is important: garbage collection timing is intentionally not observable in a predictable way.
If weak collections were iterable, code could depend on whether garbage collection had happened.
Private Metadata
WeakMap was often used for private data before class private fields.
const privateState = new WeakMap();
class Counter {
constructor() {
privateState.set(this, { count: 0 });
}
increment() {
privateState.get(this).count += 1;
}
}
The instance is the key. The private state is associated externally.
Modern private fields are often clearer for class-private data.
DOM Metadata Example
WeakMap is useful when associating metadata with DOM nodes.
const nodeState = new WeakMap();
function enhanceButton(button) {
nodeState.set(button, {
clicks: 0,
});
button.addEventListener("click", () => {
const state = nodeState.get(button);
state.clicks += 1;
});
}
When the button becomes unreachable, weak metadata does not keep it alive.
Cache Design
WeakMap can cache derived values tied to object identity.
const cache = new WeakMap();
function getExpensiveResult(object) {
if (cache.has(object)) {
return cache.get(object);
}
const result = compute(object);
cache.set(object, result);
return result;
}
This is useful when object identity is the natural cache key.
WeakRef
JavaScript also has WeakRef, which can weakly reference an object.
const ref = new WeakRef(object);
const value = ref.deref();
deref() returns the object if it is still alive, otherwise undefined.
Use WeakRef rarely. Most application code should prefer explicit lifetimes and cleanup.
FinalizationRegistry
FinalizationRegistry can register cleanup callbacks after an object is garbage collected.
This is advanced and should not be used for critical business logic because cleanup timing is not guaranteed.
It can help library-level resource cleanup, but it is not a replacement for explicit disposal.
Common Mistakes
A common mistake is expecting WeakMap entries to be enumerable. They are not.
Another mistake is using WeakMap when the key is a string or number. WeakMap keys must be objects.
A third mistake is treating weak references as deterministic cleanup tools. Garbage collection timing is intentionally nondeterministic.
Senior Trade-Offs
Use WeakMap when metadata belongs to an object but should not extend the object's lifetime.
Use Map when you need iteration, primitive keys, explicit deletion, or predictable cache management.
Use explicit cleanup for important resources.
Code or Design Example
const subscriptions = new WeakMap();
function subscribe(component, unsubscribe) {
subscriptions.set(component, unsubscribe);
}
function cleanup(component) {
const unsubscribe = subscriptions.get(component);
if (unsubscribe) {
unsubscribe();
subscriptions.delete(component);
}
}
The WeakMap avoids keeping component objects alive, but explicit cleanup is still clearer when lifecycle hooks exist.
Debugging Workflow
When diagnosing memory retention:
check strong references from Map, arrays, closures, and listeners
use WeakMap only when object identity is the key
remember WeakMap is not iterable
prefer explicit cleanup for subscriptions
inspect heap snapshots for retaining paths
avoid relying on garbage collection timing
Interview Framing
Explain that weak collections hold object keys weakly. Then emphasize why they are not iterable and where they help avoid memory retention.
Revision Notes
WeakMap and WeakSet allow object-associated data without strongly keeping those objects alive. Their contents cannot be enumerated.
Key Takeaways
Weak collections are memory-friendly association tools, not general-purpose maps. Use them when object lifetime should control metadata lifetime.
Follow-Up Questions
- What keys can WeakMap use?
- Why are primitive keys not allowed?
- Why is WeakMap not iterable?
- What is WeakSet useful for?
- How can WeakMap avoid memory retention?
- When should you use Map instead?
- What is object identity caching?
- What does
WeakRef.deref()return? - Why is FinalizationRegistry not deterministic?
- How do weak collections relate to memory leaks?
How I Would Answer This In A Real Interview
I would explain that WeakMap holds object keys weakly, so associated metadata does not keep objects alive. Then I would contrast it with Map, mention non-iterability, and give examples like DOM metadata, object identity caches, and private state.