(Functions remembering their outer scope — even after the outer function has finished)
A closure is formed when a function "remembers" the variables from its outer (lexical) scope, even after the outer function has returned.
function outer() {
let name = "Alice";
function inner() {
console.log("Hello, " + name); // name comes from outer()
}
return inner;
}
const greet = outer(); // outer() returns inner
greet(); // "Hello, Alice"Even though outer() has finished executing, inner() still remembers name because of closure.
Closures are used in:
useState, useEffectfunction secretHolder() {
let secret = "1234";
return {
getSecret: function () {
return secret;
},
setSecret: function (newSecret) {
secret = newSecret;
},
};
}
const vault = secretHolder();
console.log(vault.getSecret()); // "1234"
vault.setSecret("5678");
console.log(vault.getSecret()); // "5678"secret can't be accessed directly — only through the returned methods.
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 1000);
}
// Output: 3 3 3 (Not 0 1 2!)Fix with let:
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 1000);
}
// Output: 0 1 2 ✅Explanation: let creates a new block scope per iteration, so each i is preserved properly due to closure.
function makeMultiplier(x) {
return function (y) {
return x * y;
};
}
const double = makeMultiplier(2);
console.log(double(5)); // 10
const triple = makeMultiplier(3);
console.log(triple(5)); // 15Each returned function "remembers" its own value of x.
closure gives you access to an outer function’s variables from an inner function.preserve state across calls and enable private variables.counter() function that returns a function that increments and logs the count.greeting(name) function that returns another function saying "Hello, name".