A closure remembers bindings from its creation scope
JavaScript resolves names using lexical scope: where the function was written, not simply who called it. Each function call has its own local state. A returned function can retain access to that state after the outer call finishes.
function createCounter(start = 0) {
let count = start;
return {
next() { count += 1; return count; },
current() { return count; }
};
}
const first = createCounter(10);
const second = createCounter();
console.log(first.next()); // 11
console.log(first.next()); // 12
console.log(second.next()); // 1
console.log(first.current()); // 12The two outer calls create separate count bindings. The methods retain access to their own call's count. A closure remembers the binding, not a permanently frozen copy of its original value.
Execution context and call stack
Calling a function adds execution work to the call stack; returning removes that active call. Retained lexical data can still be reachable through a closure after the active call ends. This distinction explains why “the function returned” does not mean every object it referenced is immediately discarded.
Loop bindings
for (let index = 0; index < 3; index += 1) {
setTimeout(() => console.log(index), 0);
}
// Later: 0, 1, 2let provides per-iteration bindings here. A similar loop using var shares one binding and the callbacks usually observe the final value 3 after the loop completes. The timers do not run in the middle of the current synchronous loop.
Lifetime and accidental retention
A listener or timer can keep a closure reachable, which can in turn retain objects it needs. Remove obsolete listeners and cancel unneeded timers when a component is disposed. Do not call every closure a memory leak; retention becomes a leak when data remains reachable longer than the application requires.
Practice
- Add a reset method that restores a counter to its initial start.
- Create two counters and verify that resetting one does not reset the other.
- Predict a callback that reads a changed outer variable; it sees the current binding value when invoked.
- Trace the stack for a function calling another function, separately from the lexical scopes.
हिन्दी संकेत: closure value की पुरानी photocopy नहीं, outer binding तक access रखता है।