JavaScript Closures Explained: Why Your Functions Remember Everything
Source: Dev.to
JavaScript Closures Explained
Closures are functions that remember variables from their outer scope, even after the outer function returns. Understanding them solves common issues like the var loop bug, stale React hooks, and memory leaks.
Key Points
- Closures capture references, not values – functions hold pointers to variables, not snapshots.
- Lexical scope – what a function can access is determined by where it is written in the code, not where it is called.
varvsletin loops –varshares a single variable;letcreates a new binding per iteration.- React hooks and stale closures – closures can capture old state. Fix with dependency arrays or
useRef. - Memoization – closures can store results for performance optimization.
- Memory leaks – closures keep references alive. Always clean up event listeners and timers.
Example: Counter
function makeCounter() {
let count = 0; // closure keeps this alive
return function increment() {
count++;
return count;
};
}
const counter = makeCounter();
counter(); // 1
counter(); // 2
counter(); // 3
Closures allow count to persist even after makeCounter has returned.
React Stale Closure Fix
useEffect(() => {
const id = setInterval(() => fetchResults(query), 2000);
return () => clearInterval(id);
}, [query]); // dependency array ensures fresh state
Closures are everywhere in JavaScript; understanding them is essential to write predictable and efficient code.