🔒 Closures — The Magic of Remembering in JavaScript

Closures are one of the most fascinating (and sometimes confusing) concepts in JavaScript. But if you understand scope chain and lexical environment, closures become much easier to grasp. Let’s break it down with examples.
đź’ˇ What is a Closure?
A closure is a function that remembers its outer variables even after the outer function has finished execution. In other words, a closure gives you access to an outer function’s scope from an inner function.
đź§© Basic Example
function outer() {
let outerVar = "I am outside!";
function inner() {
console.log(outerVar);
}
return inner;
}
const myClosure = outer();
myClosure(); // "I am outside!"
What’s happening?
outer()
is called and returnsinner
function.inner
still has access toouterVar
even thoughouter()
has already finished executing.
🎯 Using Closures to Create Private Variables
function counter() {
let count = 0;
return function() {
count++;
console.log(count);
};
}
const increment = counter();
increment(); // 1
increment(); // 2
increment(); // 3
Why it works
The count
variable is in the lexical environment of the returned function. It is private and maintained across multiple calls.
đź§° Example: Factory Functions
function makeMultiplier(factor) {
return function(number) {
return number * factor;
};
}
const double = makeMultiplier(2);
const triple = makeMultiplier(3);
console.log(double(5)); // 10
console.log(triple(5)); // 15
Explanation
Each returned function "remembers" its own factor
value, creating separate multiplier functions.
⚠️ Common Pitfall: Loops and Closures
for (var i = 0; i < 3; i++) {
setTimeout(function() {
console.log(i);
}, 1000);
}
Output
3
3
3
Why?
Because var
is function-scoped and not block-scoped, all callbacks share the same i
, which ends up as 3.
How to fix it?
Use let
, which is block-scoped:
for (let i = 0; i < 3; i++) {
setTimeout(function() {
console.log(i);
}, 1000);
}
Correct Output
0
1
2
🌀 Returning Objects with Closures
function createPerson(name) {
let age = 0;
return {
getName: function() {
return name;
},
birthday: function() {
age++;
},
getAge: function() {
return age;
}
};
}
const person = createPerson("John");
console.log(person.getName()); // John
console.log(person.getAge()); // 0
person.birthday();
console.log(person.getAge()); // 1
Why it works
The returned object functions share access to name
and age
via closure.
âś… Key Takeaways
Closures allow functions to access outer scope variables even after the outer function has finished.
Useful for creating private data and factory functions.
Understand
var
vslet
inside loops to avoid common mistakes.
Subscribe to my newsletter
Read articles from pushpesh kumar directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
