Benefits of closures
What a closure is
A closure is a function that "remembers" its lexical (outer) scope, even when it runs outside that scope.
More simply put:
A closure is a function's ability to reach variables from the place where it was created, not from where it is called.
Example 1 - basic
function outer() {
let count = 0;
function inner() {
count++;
console.log(count);
}
return inner;
}
const counter = outer();
counter(); // 1
counter(); // 2
counter(); // 3What happens:
outer()returnsinner();inner()remembered thecountvariable from its lexical environment;- even after
outer()has finished,countdoes not disappear; - this is exactly what a closure is, the function's "saved memory".
Example 2 - private variables
function createUser(name) {
let score = 0;
return {
getName() {
return name;
},
addScore() {
score++;
},
getScore() {
return score;
}
};
}
const alice = createUser('Alice');
alice.addScore();
alice.addScore();
console.log(alice.getName(), alice.getScore()); // Alice 2Here score is a private variable:
it is not accessible from outside (alice.score does not exist),
but is accessible from the getScore and addScore closures.
This is how encapsulation and private data are implemented without classes.
Example 3 - function generators (factories)
function makeMultiplier(factor) {
return function(num) {
return num * factor;
};
}
const double = makeMultiplier(2);
const triple = makeMultiplier(3);
console.log(double(5)); // 10
console.log(triple(5)); // 15factor "lives" inside each function.
That is, each function "remembers" what multiplier it was created with.
Example 4 - event handlers
function setupButton(id) {
let clicks = 0;
document.getElementById(id).addEventListener('click', () => {
clicks++;
console.log(`Click on button ${id}: ${clicks}`);
});
}
setupButton('save');
setupButton('cancel');Each handler "remembers" its own clicks variable,
even after exiting setupButton.
Example 5 - caching (memoization)
function memoize(fn) {
const cache = {};
return function(arg) {
if (cache[arg]) {
console.log('From cache:', arg);
return cache[arg];
}
const result = fn(arg);
cache[arg] = result;
console.log('Computed:', arg);
return result;
};
}
const square = memoize(x => x * x);
square(4); // Computed: 4
square(4); // From cache: 4cache is preserved between calls through the closure.
How this works "under the hood"
When a function is created, JS forms a lexical environment - an object where all variables declared inside are stored.
If an inner function uses variables from an outer scope, it remembers a reference to that environment.
So even after the outer function finishes, the inner functions can still access its variables.
Closures are created automatically
You don't need to do anything special, every time you create a function inside another one, JS creates a closure.
function outer() {
const a = 42;
return function() {
console.log(a); // closure
};
}Where closures are used in real life
| Scenario | Example |
|---|---|
| Private data | Hiding variables inside a function |
| Function factories | Generators, configurable handlers |
| Modules and encapsulation | Splitting logic without global variables |
| Caching (memoization) | Storing computation results |
| Counters and state | Keeping state between calls |
| Callbacks and event handlers | Access to outer data inside a function |
| Functional programming | Currying, partial application, compose, etc. |
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.