- Home
- /
- Tutorials
- /
- JavaScript Tutorial
- /
- JavaScript Closures
JavaScript Scope & Hoisting
JavaScript Closures
A JavaScript closure is a function that remembers the variables around it, even after the outer function has finished.
The inner function keeps a live link to the scope it was created in.
This is how a function can hold private state between calls.
Example
Example
javascript
function makeCounter() {
let count = 0;
return function () {
count++;
return count;
};
}
const counter = makeCounter();
console.log(counter());
console.log(counter());The output is 1 then 2.
count survives even though makeCounter has already returned.
What is a Closure?
A closure is created whenever a function is defined inside another function.
The inner function carries the outer scope with it wherever it goes.
Nothing special has to be written: closures happen automatically because of how scope works.
Syntax
Syntax
javascript
function outer() {
let value = 0;
return function inner() {
return value;
};
}inner can still read value after outer has finished.
Private Data
A closure is the normal way to keep a value that nothing else can reach.
The variable is not a property, so no outside code can read or change it directly.
Example
Example
javascript
function createAccount(start) {
let balance = start;
return {
deposit: function (amount) {
balance += amount;
return balance;
},
getBalance: function () {
return balance;
}
};
}
const account = createAccount(100);
console.log(account.deposit(50));
console.log(account.getBalance());balance can only be changed through the two functions provided.
Function Factories
A closure lets you build specialised functions from a general one.
Example
Example
javascript
function multiplyBy(factor) {
return function (n) {
return n * factor;
};
}
const double = multiplyBy(2);
const triple = multiplyBy(3);
console.log(double(5));
console.log(triple(5));Each returned function remembers its own factor.
Each Call Gets Its Own Scope
Calling the outer function again creates a completely separate closure.
Example
Example
javascript
function makeCounter() {
let count = 0;
return function () {
count++;
return count;
};
}
const a = makeCounter();
const b = makeCounter();
console.log(a());
console.log(a());
console.log(b());a reaches 2 while b is still at 1; they do not share count.
Closures in Loops
This is the clearest everyday example of closures at work.
With let, each turn creates a new binding for the closure to capture.
Example
Example
javascript
const functions = [];
for (let i = 1; i <= 3; i++) {
functions.push(function () {
return i;
});
}
console.log(functions[0]() + "," + functions[1]() + "," + functions[2]());The output is 1,2,3.
With var all three would return 4, because they would share one variable.
Closures Hold Memory
A closure keeps its outer variables alive for as long as the inner function exists.
That is usually what you want, but holding many large closures can use more memory than expected.
Example
Example
javascript
function once(fn) {
let called = false;
let result;
return function (...args) {
if (!called) {
called = true;
result = fn(...args);
}
return result;
};
}
const setup = once(() => "ready");
console.log(setup());
console.log(setup());Here the closure remembers whether the function has already run.
Complete Example
Complete Example
html
<!DOCTYPE html>
<html>
<head>
<title>JavaScript Closures</title>
</head>
<body>
<h1>JavaScript Closures</h1>
<p id="result"></p>
<script>
function makeCounter() {
let count = 0;
return function () {
count++;
return count;
};
}
const counter = makeCounter();
document.getElementById("result").innerHTML =
counter() + ", " + counter() + ", " + counter();
</script>
</body>
</html>Try It Yourself
Run the above example in the Try It Editor.
Try a second counter:
Create another counter with makeCounter() and confirm it starts again at 1.
Important Points
- A closure is a function that remembers the scope it was created in.
- The remembered variables survive after the outer function returns.
- Closures are how JavaScript keeps private data.
- Each call to the outer function creates a separate closure.
- Closures keep their variables in memory for as long as they exist.
Conclusion
JavaScript closures let a function carry its surrounding scope with it.
They power counters, private data, function factories and much of the async code you will meet later.
Understanding closures is one of the biggest steps from beginner to confident JavaScript.
