A closure is a function that remembers where it was born
Here comes the star idea of this module, and it's not as hard as it sounds.
Picture every function, the moment it's born, grabbing a backpack with the variables it had on hand right then. Even if the function travels off to another part of the program and its birthplace no longer exists, it keeps carrying that backpack and can still look inside. That's a closure: a function that remembers the world where it was born.
Why should you care? Because closures power things you use every day: counters, unique ID generators, private data nobody can touch from outside, even React hooks. Nail this and half of modern libraries stop looking like magic.
Classic example: a counter with memory
function makeCounter() {
let count = 0; // "private" variable
return function () {
count = count + 1; // remembers and modifies count
return count;
};
}
const counter = makeCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3
The count variable does not exist outside makeCounter: nobody can read it
or change it from outside. But the returned function carries it in its backpack, so
it remembers it and updates it between calls. You just created a piece of private
data.
Each closure has its own backpack
const a = makeCounter();
const b = makeCounter();
console.log(a()); // 1
console.log(a()); // 2
console.log(b()); // 1 (independent from a)
Each call to makeCounter hands out a fresh backpack, so a and b never step on
each other. It's like giving every user their own safe.
Why do they matter in the real world?
- Private data:
countis untouchable from outside, like a balance that only moves through the function you expose. - Unique ID generators: a closure that keeps the last number and returns the next one each time.
- Function factories: building tailor-made functions (one that multiplies by 2, another by 10) that remember their own setup.
- React and friends: hooks like
useStatelean on exactly this idea to remember your state between renders.
Once the backpack clicks, you've unlocked one of JavaScript's superpowers.
Examples
The backpack holds the greeting: hello and bye each remember their own
function makeGreeting(greeting) {
return function (name) {
return greeting + ", " + name;
};
}
const hello = makeGreeting("Hello");
const bye = makeGreeting("Goodbye");
console.log(hello("Ann")); // "Hello, Ann"
console.log(bye("Ann")); // "Goodbye, Ann"