Encapsulation
Keep mutable state private behind a returned function.
JS Puzzles · Const
Closures let functions retain access to variables from the lexical environment where they were created. This supports persistent state, private data, and callbacks that run after their surrounding function has finished.
A closure is a function together with the lexical environment where it was created. JavaScript functions retain a reference to that environment, allowing them to read or change outer variables later; variable lookup proceeds from the current environment outward through the scope chain.
function outer() { const value = ...; return function inner() { ...value... }; }function makeCounter() {
let count = 0;
return () => ++count;
}
const counter = makeCounter();
console.log(counter()); // 1
console.log(counter()); // 2The returned function keeps access to count after makeCounter has finished, so each call updates the same private variable.
Keep mutable state private behind a returned function.
Preserve context for callbacks executed later.
Build configurable functions by capturing setup values.
A closure combines a function with the lexical environment in which that function was created. The function can later access variables from that environment even after the surrounding call has returned.
Follow-up: What determines which variable is read when several scopes use the same name? Lookup starts in the innermost environment and continues outward, so the nearest binding wins.
Each function call creates a new lexical environment for its parameters and local variables. A returned inner function retains the relevant environment, which lets separate calls maintain separate captured state.
Follow-up: Why do two counters made by the same factory not share state? Each factory call creates a distinct environment, and each returned function closes over its own environment.
let and const create block-level bindings, while var is scoped to the current function or script. In a loop, block-scoped bindings can give iterations distinct captured values; var commonly leaves callbacks sharing one binding.
Follow-up: How can the var loop issue be avoided? Use let for the loop variable or create a separate scope for each iteration.
Lexical EnvironmentEnvironment Recordouter lexical environmentletconstvar