foundation

Lexical scope and closures

Lexical environments, captured variables, module state, callback state, and memory retention.

Lexical scope is determined by where code is written, not where a function is called. A closure preserves access to bindings from its outer lexical environment after the outer function returns.

Closures power callbacks, module state, factories, React hooks, and private state. The closure captures the binding (variable cell), not a snapshot of the value at creation time — unless you create a new binding per iteration.

					for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 0); // 3, 3, 3
}
for (let j = 0; j < 3; j++) {
  setTimeout(() => console.log(j), 0); // 0, 1, 2
}
				

Watch memory: closures can retain large objects. In UI code, stale closures happen when captured values are not refreshed.

On interviews, explain the concept with a concrete example and name the runtime behavior interviewers probe.

Common pitfalls include mixing similar APIs and forgetting edge cases during live coding.

The trade-off is often clarity versus performance or safety versus convenience.

Checklist:

  • Explain lexical versus dynamic scope.
  • Capture bindings, not copied values.
  • Use let for per-iteration bindings.