JavaScript closures explained simply
October 31, 2026 · 2 min read
A closure is a function that keeps access to the variables from the place it was written, even after the outer function has finished. That is how a function can "remember" a value between calls.
Build a counter factory
function makeCounter() {
let count = 0;
return () => {
count += 1;
return count;
};
}
const orders = makeCounter();
const returns = makeCounter();
console.log(orders());
console.log(orders());
console.log(returns());
console.log(orders());
Output:
1 2 1 3
What is happening
makeCounter()creates acountvariable and returns the inner arrow function.makeCounterhas finished running, but the inner function still usescount, so JavaScript keeps it alive. The function plus the variables it remembers is the closure.- Each call to
makeCounter()creates a freshcount. That is whyreturns()starts at 1 whileorders()carries on. - Nothing outside can touch
count. The only way to change it is to call the function, which makes it private state.
Closures are also handy for settings. A factory can bake in a value, such as a tax rate, so each function it returns carries its own:
function makePricer(taxRate) {
return (price) => (price * (1 + taxRate)).toFixed(2);
}
const withVat = makePricer(0.2);
const withSalesTax = makePricer(0.08);
console.log(withVat(50)); // 60.00
console.log(withSalesTax(50)); // 54.00
Each pricer remembers the taxRate it was created with, and the two never interfere.
Common mistake
Creating functions in a loop with var. A var belongs to the whole function, so every inner function shares one variable:
const fns = [];
for (var i = 0; i < 3; i++) fns.push(() => i);
console.log(fns.map((f) => f())); // [ 3, 3, 3 ]
Use let instead. It gives each pass of the loop its own variable:
const ok = [];
for (let j = 0; j < 3; j++) ok.push(() => j);
console.log(ok.map((f) => f())); // [ 0, 1, 2 ]
Takeaway
When an inner function uses a variable from its outer function, it keeps that variable after the outer function returns. Call the outer function again and you get a new, separate copy.