What is a closure in JavaScript?
A closure is a function that remembers the variables from the place where it was created, even after that outer function has finished running.
Explain it simply
Think of a function as a person leaving home with a backpack. Whatever was in the room when they left (the variables around them) goes into the backpack. Even when they are far away and the room is gone, they can still open the backpack and use those things. That backpack is the closure.
In JavaScript, every function keeps a link to the scope where it was defined. When an outer function returns an inner function, the inner function still has access to the outer function's variables. Those variables are not copied; the inner function keeps a live reference to them, so it can read and change them later.
Example
function makeCounter() {
let count = 0; // private: only the inner function can see it
return function () {
count += 1;
return count;
};
}
const counter = makeCounter();
console.log(counter()); // Output: 1
console.log(counter()); // Output: 2
const another = makeCounter();
console.log(another()); // Output: 1Each call to makeCounter creates a new count. The first counter and the second counter each have their own backpack, so they do not share numbers.
How it works
When JavaScript runs makeCounter, it creates an environment that holds count. Normally that environment would be thrown away when the function ends. But the returned function still points to it, so the garbage collector keeps it alive for as long as the inner function exists.
Real-world use
- Private state: counters, caches and settings that outside code cannot change directly.
- Event handlers: a click handler that remembers which item it belongs to.
- Function factories:
makeMultiplier(2)returns a function that doubles numbers. - Debounce and throttle: the timer id lives inside a closure between calls.
Common mistakes
- Thinking the variable is copied. It is shared: if the outer variable changes, the closure sees the new value.
- Using
varinside a loop with callbacks. All callbacks share one variable, so they all see the last value. Uselet, which creates a new binding for each loop iteration. - Accidentally keeping large objects alive by closing over them, which can waste memory.
What to say in the interview
"A closure is a function bundled with references to the variables in the scope where it was created. Because JavaScript uses lexical scoping, an inner function can keep using the outer function's variables even after the outer function has returned. I use closures for private state, like a counter or a cache, and they are what make patterns like debounce work. One thing to watch is that closures capture variables, not values, which is why var in a loop gives surprising results."
Follow-up questions
- Why does a
forloop withvarandsetTimeoutprint the same number every time? - How would you build a
oncefunction that runs only the first time? - Can closures cause memory leaks?
Go deeper
Read these once the basics above feel easy.
The classic loop bug: with var i, there is only one i for the whole loop, so every callback reads its final value. With let i, JavaScript creates a fresh binding per iteration, so each callback remembers its own number. Before let existed, people wrapped the body in an immediately invoked function to create a new scope.