A closure is created when a function remembers and can access variables from its outer (lexical) scope, even after that outer function has finished executing.
Closures allow JavaScript functions to maintain state, hide data, and build powerful abstractions that are used everywhere in modern code (callbacks, event handlers, modules, and more).
Typical closure pattern in JavaScript:
function outer() {
let count = 0;
function inner() {
count++;
console.log(count);
}
return inner;
}
const counter = outer();
counter(); // 1
counter(); // 2
counter(); // 3
function makeAdder(x) {
return function (y) {
return x + y;
};
}
const add5 = makeAdder(5);
console.log(add5(10)); // 15
const add10 = makeAdder(10);
console.log(add10(3)); // 13
function secretBox() {
let secret = "Hidden";
return {
getSecret: () => secret,
setSecret: (value) => (secret = value),
};
}
const box = secretBox();
console.log(box.getSecret()); // Hidden
box.setSecret("New value");
console.log(box.getSecret()); // New value
for (let i = 1; i <= 3; i++) {
setTimeout(() => {
console.log("Iteration:", i);
}, 1000 * i);
}
count lives in the outer function outer. The inner function inner forms a closure over count, so every call to counter() increments the same shared value: 1 → 2 → 3.makeAdder, each call (e.g. makeAdder(5)) creates a new closure with its own copy of x. That is why add5 and add10 remember different values.secretBox, the variable secret is private to the closure. It cannot be accessed directly from outside, only through getSecret and setSecret.let ensures each iteration has its own i value. Each arrow function scheduled with setTimeout closes over the correct i.makeAdder).Because closures keep references to outer variables, those variables stay in memory as long as the inner function is reachable. This is normally fine and very useful, but:
null or reassign) if they are no longer needed.makeAdder).let and const in loops to avoid unexpected behavior in asynchronous callbacks.multiplier(n) that returns a function multiplying its input by n, e.g. double = multiplier(2).increment(), decrement(), and reset() methods, all sharing the same internal count.setTimeout to print numbers 1 through 5 with a 1-second gap between each log.