What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more
A JavaScript closure is a function that retains access to names in the lexical environment where it was created. That lets a function use surrounding variables later—even after the outer function has returned. This guide uses JavaScript throughout; other languages use different syntax and may define capture behavior differently.
How can a function remember a variable?
JavaScript resolves a name according to where code is written, not where a function is eventually called. This is called lexical scoping. A closure is a function together with access to its surrounding lexical environment, as described in MDN’s JavaScript closures guide and its closure glossary entry.
Start with an inner function that reads a variable from the function around it:
Do these 3 things before closing this tab:
1Fix the driver behind crashes, sound loss and screen glitches2Clear out junk files and repair common Windows errors3Scan for outdated or missing drivers - takes under a minutefunction makeGreeter(name) {
function greet() {
return `Hello, ${name}!`;
}
return greet;
}
const greetMina = makeGreeter("Mina");
console.log(greetMina()); // Hello, Mina!
makeGreeter assigns a parameter named name, then returns greet. The call to makeGreeter finishes before greetMina() runs, but the returned function can still resolve name from the environment in which it was created. That continuing access is the closure.
#1 Best Overall
The closure is not special punctuation or a separate kind of function. It describes the relationship between a function and the surrounding environment it can access.
What does a closure capture: a value or a binding?
It is more useful to think of a closure as retaining access to a binding—the named place a variable refers to—than as automatically taking a frozen copy of its value. If the binding changes and the closure can still access it, a later call can observe the updated value.
function makeCounter() {
let count = 0;
return function () {
count += 1;
return count;
};
}
const nextCount = makeCounter();
console.log(nextCount()); // 1
console.log(nextCount()); // 2
The returned function can both read and update count. Each call to makeCounter() creates a separate environment, so separate counters have separate bindings:
Rank #2
const first = makeCounter();
const second = makeCounter();
first();
console.log(first()); // 2
console.log(second()); // 1
Closures do not all behave as though they copy values at creation time. The result depends on the language’s capture rules and on whether the surrounding binding is changed. In Swift, for example, the official language guide describes closures as self-contained blocks that can be passed around and that can capture constants and variables from their defining context; its terminology and syntax differ from JavaScript. See Swift’s closures guide.
Where are closures useful?
Creating specialized functions
A function factory returns functions configured with different values. MDN illustrates this with a makeAdder(x) pattern: each returned function can add the particular x supplied when the factory was called.
function makeAdder(amount) {
return function (number) {
return number + amount;
};
}
const addFive = makeAdder(5);
const addTen = makeAdder(10);
console.log(addFive(3)); // 8
console.log(addTen(3)); // 13
addFive and addTen use the same function logic but retain access to different amount bindings.
Keeping state behind functions
The counter example uses a closure to keep count out of the surrounding code’s direct reach while exposing an operation that updates it. A closure can therefore help associate state with functions that act on it. This can resemble an object with a method, but closures and objects are not interchangeable in every design.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Handling callbacks that run later
A callback is a function passed to other code to be called later—for example, when an event occurs. If the callback needs a surrounding variable, a closure lets it retain access to that context after the code that registered it has continued.
function registerGreeting(button, name) {
button.addEventListener("click", function () {
console.log(`Hello, ${name}!`);
});
}
The event handler runs when the button is clicked, not when registerGreeting creates it. Its closure gives it access to the name binding from that call.
Rank #4
Why can callbacks in a JavaScript loop show the wrong value?
A classic JavaScript pitfall occurs when a loop declares its counter with var and registers callbacks that read it. Because var is function-scoped rather than block-scoped, the callbacks can share one binding. If they run after the loop finishes, they may all read the final value associated with that binding—not separate values from each iteration.
for (var i = 0; i < 3; i++) {
setTimeout(function () {
console.log(i);
}, 0);
}
In this example, the callbacks run after the loop has advanced i to 3, so each logs 3. The issue is not that closures always capture a final value: these callbacks share a single changing, function-scoped binding.
For this loop pattern, declaring the counter with let gives each iteration its own block-scoped binding:
Best Value
for (let i = 0; i < 3; i++) {
setTimeout(function () {
console.log(i);
}, 0);
}
These callbacks log 0, 1, and 2. MDN’s closures guide also shows a function-factory approach that creates a separate environment for each callback; the right fix depends on the code’s purpose.
How can you recognize a closure?
- A function refers to a name declared outside its own body.
- That function is passed elsewhere, returned, or called after the surrounding code has continued.
- The function still needs that surrounding binding when it runs.
When tracing a confusing example, identify where the function was written, list the outer names it refers to, and check whether those bindings are shared or changed before the function runs. That separates lexical scope from the later call site and helps explain what the closure can observe.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.
Free tools Windows power users keep installed
One-click scans. No signup required.

