On this page · sections
JavaScript Memory & Garbage Collection
Can you explain why an object is still alive — and which frontend patterns accidentally keep it that way?
JavaScript does not expose free(). GC collects unreachable objects. Leaks are extra reachability: listeners, caches, closures, detached DOM, timers.
These questions test:
- Reachability from roots
- Common SPA leak patterns
- Why
WeakMapexists - Closures vs retained graphs
- What you can (and cannot) measure in DevTools
Questions
GC
Tools
Senior-Level Follow-ups
GC
1. Reachability and Roots
Why This Matters
“The variable went out of scope” is not enough. Another path may still point at the object.
Problem
When is an object eligible for collection?
Example
Roots
→ global / module bindings
→ current stack locals
→ host handles (DOM, timers, registered listeners)If a path exists from a root, the object stays.
function make() {
const big = new Array(1e6).fill("x");
return () => big.length;
}
let hold = make();big lives as long as hold does.
Engines use mark-and-sweep (with generational / incremental variants). Young objects die fast; survivors are promoted.
Interview Answer
“GC follows reachability from roots. I reason in graphs: who still points at this? Collection is nondeterministic. Clearing the last reference makes the object eligible, not immediately freed.”
2. Common Leak Patterns
Why This Matters
SPAs never unload the page. A leak per navigation is a crash over a workday.
Problem
Name the leaks you actually see in frontend apps.
Example
Forgotten listeners
window.addEventListener("resize", onResize);
// missing removeEventListenerTimers
setInterval(poll, 5000);
// missing clearIntervalGlobal / module caches
const cache = new Map();
cache.set(user, hugePayload);Subscriptions
Redux, WebSocket, and subscribe() without unsubscribe.
Closures in long-lived callbacks that capture large trees.
Interview Answer
“Leaks are retained references. I look at listeners, intervals, module Maps, and subscriptions first. Each mount needs a matching cleanup. Caches need bounds or WeakMap keys.”
Tools
3. WeakMap as Non-Owning Storage
Problem
When does WeakMap fix a leak that Map cannot?
Example
const extra = new WeakMap();
extra.set(node, computed);
node.remove();
// node can be collected; extra entry goes with itIf you need to iterate the cache, WeakMap cannot help. Use a Map plus explicit delete or a bounded LRU — LRU Cache.
WeakRef and FinalizationRegistry exist but are easy to misuse. Prefer WeakMap for metadata.
Interview Answer
“WeakMap keys are weak. I use it for per-object metadata whose lifetime should match the object. If I need listing, eviction, or persistence, I use a strong Map with a policy.”
4. Closures and Accidental Retention
Problem
Does returning a small function keep a large sibling binding alive?
Example
function load() {
const huge = fetchPayload();
const id = huge.id;
return () => id;
}Spec-wise the environment can retain huge. Engines may optimize if huge is unused. Do not rely on it.
If the returned function logs huge, or a method on a retained object closes over it, it stays.
Split the factory so the large data is not in the same environment as the long-lived callback.
Interview Answer
“A closure keeps its environment reachable. I assume unused locals can still pin memory unless I have measured otherwise. I do not close over large objects in handlers that outlive a view.”
Senior-Level Follow-ups
5. Detached DOM
const node = document.getElementById("panel");
window.cache = node;
node.remove();The node is out of the document but still alive. Its listeners and child graph stay too.
Null the cache. Prefer WeakMap keyed by the node if you must store extras.
6. Can You Force GC?
Not in portable JS. Chrome DevTools can collect; Node --expose-gc plus global.gc() is a test hook.
global.gc is not an application API.
7. What I’d Profile
Heap snapshot → compare retained size.
Allocation timeline → who allocates in a click handler.
Look for:
- Detached HTMLElement growing
- Listener count growing
- A Map whose size only increases
Fix the reference. Do not “tune GC.”
Final Interview Strategy
1. Alive = reachable from a root
2. SPAs make leaks permanent
3. Pair every subscribe with unsubscribe
4. WeakMap for object metadata
5. Closures retain environments
6. Detached DOM is still a graph
7. Measure with heap snapshots, don't guessSenior-level signal: Name the retaining path. GC trivia without a leak story is not a senior answer.