Skip to content

Closures

A closure is a function that β€œremembers” the variables from the scope it was created in, even after that outer scope has finished executing. This is possible because of JavaScript’s lexical scoping β€” a function’s access to variables is determined by where it’s defined, not where it’s called.

function makeCounter() {
let count = 0; // this variable is "closed over"
return function () {
count += 1;
return count;
};
}
const counter = makeCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3 -- `count` persisted between calls
function makeMultiplier(factor) {
return (n) => n * factor; // remembers `factor` from the outer scope
}
const double = makeMultiplier(2);
console.log(double(5)); // 10

Creating closures inside a loop using var β€” since var is function-scoped (not block-scoped), every closure ends up sharing the same variable, which holds its final value by the time the closures run.

for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 0);
}
// prints 3, 3, 3 -- all closures share the same `i`
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 0);
}
// prints 0, 1, 2 -- `let` creates a new binding per iteration
  1. Why does makeCounter() remember count between calls?

    AnswerThe inner function forms a closure over count β€” it keeps a live reference to that variable in its enclosing scope, which persists as long as the closure exists.
  2. Why does using var in a loop with setTimeout print the same value every time?

    Answervar is function-scoped, so all iterations share one variable; by the time the timeouts fire, the loop has finished and the variable holds its final value.
  3. What fixes the loop-closure bug from question 2?

    AnswerUsing let instead of var β€” let creates a fresh, block-scoped binding for each iteration.