A closure is a function that remembers the lexical scope it was declared in.
Building a counter
function createCounter() {
let count = 0;
return {
increment: () => ++count,
current: () => count,
};
}
const counter = createCounter();
counter.increment();
counter.increment();
console.log(counter.current()); // 2Nothing outside can touch count, yet the returned functions keep a live reference to it.
The classic trap: loops and var
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i)); // 3, 3, 3
}Switch to let and each iteration gets a fresh binding, so you'll see 0, 1, 2.
Takeaways
- Reach for closures when you want private state.
- Long-lived closures keep their captured values in memory — be deliberate.