Closures in JavaScript
How Functions Remember Things

In the previous blog, we understood how JavaScript executes code behind the scenes using concepts like hoisting, creation phase, and execution phase.Now we move into something that feels almost like magic when you first see it.
Closures.
Closures are one of those concepts that seem simple when explained, but take time to truly understand. And once you do understand them, a lot of advanced JavaScript suddenly starts making sense.
Why Closures Matter
Let’s start with a simple question. When a function finishes executing, what happens to its variables?
Most people would say they are destroyed. And in most cases, that is true.
But not always.
A Strange Example
function outer() {
let count = 0;
function inner() {
count++;
console.log(count);
}
return inner;
}
const counter = outer();
counter(); // 1
counter(); // 2
counter(); // 3
Now pause and think.
The function outer() has already finished executing. So how is count still increasing? Why is it not reset to 0 every time? This behavior is what closures explain.
What is a Closure?
A closure is created when a function remembers variables from its outer scope even after that outer function has finished executing.
In simple terms:
A function + its surrounding state = closure
Breaking Down the Example
function outer() {
let count = 0;
function inner() {
count++;
console.log(count);
}
return inner;
}
When outer() runs:
countis createdinneris definedinneris returned
Now here is the key part. When inner is returned, it does not just return the function. It returns the function along with access to count.
That combination is the closure.
Mental Model
Think of it like this:
The inner function carries a backpack
Inside the backpack are all the variables it needs
Even if the outer function is gone, the backpack stays
So inner keeps access to count.
Important Point
Closures do not store values.
They store references to variables.
That is why the value updates.
Another Example
function createMultiplier(multiplier) {
return function(num) {
return num * multiplier;
};
}
const double = createMultiplier(2);
const triple = createMultiplier(3);
console.log(double(5)); // 10
console.log(triple(5)); // 15
Each function remembers its own multiplier. This is closure in action.
Closures and Lexical Scope
Closures are based on something called lexical scope. Lexical scope means: A function can access variables defined in its outer scope.
function outer() {
let name = "Shikhar";
function inner() {
console.log(name);
}
inner();
}
The inner function can access name. Closures take this one step further. They preserve this access even after the outer function is done.
Closures with Loops
for (var i = 1; i <= 3; i++) {
setTimeout(function() {
console.log(i);
}, 1000);
}
Output:
4
4
4
Why? Because var is function scoped. All functions share the same i.
Fix with let
for (let i = 1; i <= 3; i++) {
setTimeout(function() {
console.log(i);
}, 1000);
}
Output:
1
2
3
Because let creates a new scope for each iteration.
Fix with Closure
for (var i = 1; i <= 3; i++) {
(function(j) {
setTimeout(function() {
console.log(j);
}, 1000);
})(i);
}
Each iteration creates a new closure with its own j.
Data Privacy Using Closures
Closures allow you to create private variables.
function createCounter() {
let count = 0;
return {
increment: function() {
count++;
},
getCount: function() {
return count;
}
};
}
const counter = createCounter();
counter.increment();
counter.increment();
console.log(counter.getCount()); // 2
Here, count cannot be accessed directly. It is protected inside the closure.
Closures in Real Applications
Closures are used everywhere:
Event handlers
Callbacks
Timers
Modules
State management
Example:
function setupButton(button) {
let clicks = 0;
button.addEventListener("click", function() {
clicks++;
console.log(clicks);
});
}
Each button remembers its own click count.
Common Mistakes
Thinking closures copy values
Not understanding reference behavior
Confusing scope with closure
Ignoring how loops interact with closures
Performance Consideration
Closures keep references alive. If not used properly, they can lead to memory issues. But in most cases, this is not something you need to worry about early on.
Putting It All Together
function createUser(name) {
let loginCount = 0;
return {
login: function() {
loginCount++;
console.log(name + " logged in " + loginCount + " times");
}
};
}
const user = createUser("Shikhar");
user.login();
user.login();
This combines:
closures
private state
reusable logic
Final Thought
Closures are not a special feature. They are a natural result of how JavaScript handles scope and functions. But understanding them properly changes how you think about code. Instead of just writing functions, you start controlling data flow and state. And that is where JavaScript starts becoming powerful.






