Closures in JavaScript: The Function That Remembers
Have you ever seen a function that somehow “remembers” something — even after the program has moved on?
Related articles
See all


Have you ever seen a function that somehow “remembers” something — even after the program has moved on?


If yes, then you’ve already encountered closures.
If not, don’t worry. It’s not a bug.
It’s not a glitch in the matrix.
It’s one of the most powerful — and misunderstood — features of JavaScript.
And today, we’ll explain it in the simplest way possible.
Let’s start small:
function createCounter() {
let count = 0;
return function () {
count++;
console.log(count);
};
}
const counter = createCounter();
counter(); // 1
counter(); // 2
counter(); // 3Every time we call counter(), the number increases:1… 2… 3…
But wait.
createCounter() has already finished executing.
So how does count still exist?
A closure is something very simple:
A function retains access to the variables of the scope where it was created — even after that outer scope has finished executing.
In other words:
The function doesn’t forget where it came from.
It carries a small “memory pocket” with it.
Let’s explain it in gaming terms.
Imagine you’re playing an RPG.
You complete a quest.
You gain XP.
You collect loot.
You level up.
Then you save the game.
The next day, you load it again — and your character remembers:
Your level
Your items
Your gold
The choices you made
The quest is over.
But the game didn’t forget.
That’s exactly what a closure does.
The outer function finishes.
But the inner function remembers.
Closures are everywhere in JavaScript — often without you realizing it.
When you write:
const [count, setCount] = useState(0);Your component “remembers” its state across renders.
That behavior relies heavily on closures.
When you pass a function into another function:
setTimeout(() => {
console.log("Hello!");
}, 1000);The callback still has access to the variables from its surrounding scope.
That’s a closure.
When you attach an event handler:
button.addEventListener("click", () => {
console.log("Clicked!");
});That function keeps access to whatever variables existed when it was created.
Again — closure.
Closures allow you to create truly private variables:
function createSecret() {
let hidden = "Only I know this";
return function () {
console.log(hidden);
};
}There’s no way to access hidden directly from outside.
It’s like a secret chest in a dungeon that only the returned function can open.
Closures allow you to:
Create private state
Build factories
Encapsulate logic
Avoid global variables
Write functional patterns cleanly
Without closures, modern JavaScript frameworks wouldn’t exist as we know them.
React, Node.js patterns, middleware systems — they all rely on this concept.
Closures aren’t magic.
They’re just how JavaScript’s lexical scoping works.
But once you understand them, a huge part of the language suddenly makes sense.
And that’s when JavaScript stops feeling random…
…and starts feeling intentional.
