Closures Best Practices in Modern JavaScript
Closures are powerful. Here are the best practices to use them safely and avoid common pitfalls.
Closures Best Practices in Modern JavaScript
Closures are everywhere in JavaScript. Here are the best practices to use them well and avoid pitfalls.
1. Use let in Loops, Not var
// bad: var causes the closure bug for (var i = 0; i < 3; i++) { setTimeout(() => console.log(i), 0); // 3, 3, 3 } // good: let creates a fresh binding per iteration for (let i = 0; i < 3; i++) { setTimeout(() => console.log(i), 0); // 0, 1, 2 } `` ### 2. Do Not Close Over Large Objects Unnecessarily ```js // bad: keeps big alive function foo() { const big = new Array(1_000_000); return () => big.length; } // good: only keeps the number function foo() { const big = new Array(1_000_000); const len = big.length; return () => len; } `` ### 3. Remove Event Listeners and Timers ```js // bad: handler lives forever button.addEventListener("click", () => { ... }); // good: remove when done const handler = () => { ... }; button.addEventListener("click", handler); // later: button.removeEventListener("click", handler); // good: clear timers const id = setInterval(() => { ... }, 1000); // later: clearInterval(id); `` ### 4. Use Functional `setState` in React ```js // bad: stale closure setCount(count + 1); // good: latest state setCount(c => c + 1); `` ### 5. Use `bind` or Arrows for `this` in Callbacks ```js // bad: this is lost setTimeout(obj.method, 0); // good: bind or arrow wrapper setTimeout(obj.method.bind(obj), 0); setTimeout(() => obj.method(), 0); `` ### 6. Use Closures for Data Privacy, Not for Everything ```js // good: privacy needed function createCounter() { let count = 0; return { increment: () => ++count, getCount: () => count }; } // overcomplicated: no privacy needed function createName() { let name = ""; return { set: (n) => { name = n; }, get: () => name }; } // simpler: just use a plain object const nameObj = { name: "" }; `` ### 7. Keep Closures Short-Lived in Long-Running Apps In SPAs and servers, avoid accumulating closures in long-lived data structures. Remove handlers, clear timers, and bound caches. ### 8. Use `WeakMap` for Caches ```js const cache = new WeakMap(); // entries are removed when the key is GC'd `` ### 9. Name Your Closures for Better Stack Traces ```js // bad: anonymous, unclear stack trace setTimeout(() => { ... }, 0); // good: named, clear stack trace setTimeout(function handleTimeout() { ... }, 0); `` ### The Takeaway Use `let` in loops. Do not close over large objects. Remove listeners and timers. Use functional `setState` in React. Bind or arrow for `this`. Use closures for privacy, not for everything. Keep closures short-lived. Use `WeakMap` for caches. Name your closures for debugging.
Use let in loops, do not close over large objects, remove event listeners and timers, use functional setState in React, bind or arrow for this, use closures for privacy (not everything), keep closures short-lived, use WeakMap for caches, and name closures for debugging.
Do not close over large objects (extract what you need), remove event listeners and clear timers when done, use WeakMap for caches (entries are removed when the key is GC'd), and keep closures short-lived in long-running apps.
Use the functional form of setState (setCount(c => c + 1)) which receives the latest state. Or add the state to the useEffect dependency array. Or use useRef to hold the latest value. Or use useReducer (dispatch is stable).
No. Use closures when you need true privacy or functional patterns. For simple state that does not need privacy, a plain object or class is simpler and more readable. Overusing closures adds complexity.
Named functions produce clearer stack traces in errors. Instead of <anonymous> in the trace, you see the function name, which makes debugging much easier. This is especially important for callbacks in critical paths.
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.

