Garbage collection cannot reclaim reachable objects. Leaks arise when listeners, timers or caches retain values beyond their intended lifetime.
Step-by-step walkthrough
Step 1: Define the expected lifetime
Name the owner of the view, listener, timer and cached data. A leak investigation starts by identifying what should become unreachable after teardown. Memory that remains intentionally reachable for a bounded cache is not automatically a defect.
Step 2: Find the retaining path
A global listener can hold a callback that closes over a removed view. A timer or Map can do the same. Removing a DOM element does not remove every external reference to its model, so inspect the actual path from a long-lived root.
Step 3: Verify repeated recovery
Run multiple create-and-destroy cycles and compare retained objects after collection where the diagnostic tool permits it. Look for repeated surviving instances and their owners, not only a single high memory sample. The fix should break the unintended reference on every exit path.
Worked scenario
A window listener closes over a removed view’s model. Removing the listener releases that retention path.
function mountStatus(model) {
const handler = () => console.log(model.id);
window.addEventListener('resize', handler);
const timer = setInterval(handler, 1000);
return function dispose() {
window.removeEventListener('resize', handler);
clearInterval(timer);
};
}
// const dispose = mountStatus(model);
// Call dispose when this view's ownership ends.Walk through the example
Both resources retain the handler, and the handler retains model. Teardown must release both routes. Keeping the exact handler reference is necessary to remove the listener. The returned dispose function also closes over the model, so the caller should release its own obsolete cleanup reference when the view is gone.
Common mistake
One heap sample includes allocation churn and collection timing; growth alone does not identify the owner.
Verify the behavior
Repeat mounting and disposal, trigger resize and advance timers, then confirm old handlers do not execute. Investigate retaining paths in heap snapshots for removed models. Include failed initialization and early navigation so cleanup is not tested only on a successful lifecycle.
Interview exercise
Verify a removed view is collectible.
Answer and reasoning
Repeat mount-unmount cycles, compare snapshots after collection and inspect retaining paths. Confirm the fix across repeated cycles.
Follow-up discussion
Are cycles always leaks? Unreachable cycles can be collected; reachability from a long-lived owner is the important issue. Should every cache be cleared immediately? No, but caches need bounded lifetime and size so intentional retention does not become uncontrolled growth.
Continue learning
Compare the scenario with the JavaScript interview questions and test your understanding with the JavaScript MCQs. For terminology and implementation details, consult the reference material.