Difficulty: Advanced
What causes memory leaks in JavaScript? How do you detect and prevent them?
Memory leaks occur when the garbage collector cannot reclaim memory because objects are still referenced but no longer needed.
Common causes: 1. Forgotten event listeners: adding listeners without removing them 2. Closures holding references: closures capturing large objects unnecessarily 3. Detached DOM nodes: DOM elements removed from the tree but still referenced in JS 4. Global variables: accidentally creating globals accumulate over time 5. Timers and intervals: setInterval callbacks referencing objects 6. Caches without eviction: unbounded Maps/objects as caches
Detection: Chrome DevTools Memory tab (heap snapshots).
class ComponentFixed {
constructor() {
this._handler = this.handleResize.bind(this);
}
mount() {
window.addEventListener('resize', this._handler);
}
unmount() {
window.removeEventListener('resize', this._handler);
}
handleResize() {
console.log('Resized');
}
}
// In React: return cleanup from useEffect
// useEffect(() => {
// window.addEventListener('resize', handler);
// return () => window.removeEventListener('resize', handler);
// }, []);
The bound method reference must be stored to remove the same function that was added. Without cleanup, each mount adds another listener.
function setupLeak() {
const hugeData = new Array(1000000).fill('data');
// setInterval holds hugeData alive indefinitely
setInterval(() => {
console.log('tick', hugeData.length);
}, 1000);
}
// FIX: store and clear interval ID
function setupFixed() {
const id = setInterval(() => {
console.log('tick');
}, 1000);
return () => clearInterval(id);
}
// Detached DOM node
let cache = {};
function fixLeak() {
const el = document.createElement('div');
document.body.appendChild(el);
document.body.removeChild(el);
cache.el = null; // Release reference
}
Closures in timers hold strong references to captured variables. Removing a DOM node from the document does not free memory if JS still references it.
Memory Leak, Garbage Collection, Event Listeners, Closures, Detached DOM