JavaScript Closures Explained with Examples
Ad
What is a Closure?
A closure is a function that "remembers" the variables from the scope where it was created, even after that outer scope has finished executing. In other words, an inner function keeps access to its outer function's variables.
The Simplest Example
function makeCounter() {
let count = 0; // private variable
return function () {
count++; // inner function "closes over" count
return count;
};
}
const counter = makeCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3
Even though makeCounter() has already returned, the returned function still has access to count. That is the closure.
Why Closures Matter
- Data privacy —
countabove cannot be accessed or modified from outside. This is the classic "module pattern". - Function factories — generate customised functions.
- Callbacks & event handlers — they remember the state they were defined with.
Function Factory Example
function multiplier(factor) {
return (n) => n * factor;
}
const double = multiplier(2);
const triple = multiplier(3);
console.log(double(5)); // 10
console.log(triple(5)); // 15
The Classic Loop Gotcha
// ❌ var captures the SAME variable — prints 3, 3, 3
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100);
}
// ✅ let creates a NEW binding each iteration — prints 0, 1, 2
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100);
}
FAQs
Do closures cause memory leaks?
They can if you keep references to large objects longer than needed. Modern engines garbage-collect closed-over variables once nothing references them.
Where are closures used in real code?
React hooks (useState), debounce/throttle utilities, and any callback all rely on closures. Learn more in our JavaScript articles.
