Closures and Garbage Collection in JavaScript
Closures keep variables alive, which can cause memory leaks. Here is how to avoid them.
Closures and Garbage Collection in JavaScript
Closures keep their lexical environment alive, which prevents the garbage collector (GC) from freeing those variables. This is useful (data privacy) but can cause memory leaks.
How Closures Affect GC
Normally, when a function returns, its local variables become unreachable and the GC frees them. But if an inner function is returned or passed around and it closes over those variables, they stay alive.
function makeBigHolder() { const big = new Array(1_000_000); // large array return () => big.length; } const getLen = makeBigHolder(); // big is still alive here, because getLen closes over it `` The GC cannot free `big` because `getLen` holds a reference to the lexical environment. ### Memory Leak Pattern 1: Accumulating Handlers ```js const handlers = []; function setup() { const big = new Array(1_000_000); handlers.push(() => big.length); } setup(); setup(); setup(); // three large arrays are alive, each kept by a closure in handlers `` If `handlers` grows unbounded, memory grows unbounded. ### Memory Leak Pattern 2: Forgotten Timers ```js let count = 0; setInterval(() => { count++; console.log(count); }, 1000); // the timer callback closes over count and the timer runs forever // count is never freed `` **Fix**: `clearInterval` when done. ### Memory Leak Pattern 3: Detached DOM Elements ```js function setup() { const element = document.getElementById("btn"); element.addEventListener("click", () => { console.log(element.id); // closes over element }); } setup(); // even if element is removed from the DOM, the handler keeps it alive `` **Fix**: Remove the event listener when the element is removed, or use `WeakRef`. ### How to Avoid Closure Memory Leaks 1. **Remove handlers when done**: `removeEventListener`, `clearInterval`, `clearTimeout`. 2. **Do not close over large objects unnecessarily**: extract what you need. ```js // bad: keeps big alive return () => big.length; // good: only keeps the number const len = big.length; return () => len; `` 3. **Use `WeakRef` for optional references**: allows the GC to free the target. 4. **Keep closures short-lived**: do not accumulate them in long-lived data structures. 5. **Null out references** when no longer needed. ### The Trade-off Closures are essential for data privacy, callbacks, and functional programming. The memory cost is usually small. But for long-running applications (servers, SPAs), be mindful of closures that keep large objects alive. ### The Takeaway Closures keep their lexical environment alive, preventing GC. This is useful but can cause memory leaks: accumulating handlers, forgotten timers, and detached DOM elements. Avoid leaks by removing handlers, not closing over large objects, using `WeakRef` where appropriate, and keeping closures short-lived.
Closures keep their lexical environment alive, preventing the GC from freeing closed-over variables. This is useful for data privacy but can cause memory leaks if closures accumulate or keep large objects alive unnecessarily.
Accumulating handlers in an array, where each handler closes over a large object. As the array grows, each entry keeps its large object alive, and memory grows unbounded. Remove entries when no longer needed.
Remove handlers when done (removeEventListener, clearInterval), do not close over large objects unnecessarily (extract what you need), use WeakRef for optional references, keep closures short-lived, and null out references when no longer needed.
Yes. If an event handler closes over a DOM element and the element is removed from the DOM, the handler keeps the element in memory. Remove the event listener when the element is removed.
Extract the needed value before creating the closure. Instead of return () => big.length, do const len = big.length; return () => len. The closure captures the number, not the whole array, so big can be freed.
Ready to master React completely?
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course to dive deeper with high-quality video tutorials, solve interview questions, and a premium community.
Master React
Want to upskill yourself, crack your next interview, and get your dream job? Join our comprehensive course.

