Closure
1. 🔑 Definition of Closure
👉 A closure is created when a function “remembers” the variables from its lexical scope, even when that function is executed outside of its original scope.
Functions in JS always carry their lexical scope along with them.
This bundle (function + reference to outer scope) = Closure.
2. Basic Example
function outer() {
let a = 10;
function inner() {
console.log(a); // inner "remembers" a
}
return inner;
}
const fn = outer();
fn(); // ✅ 10
Explanation
outer()runs → createsa=10and definesinner.outer()returnsinner.Even though
outer()has finished execution,innerstill remembersa.This memory preservation is called a closure.
3. Why Closures Happen?
Because of:
Lexical Scope → function knows its parent environment.
Scope Chain → variable lookup goes outward.
Garbage Collector → JS keeps variables alive if they’re still referenced.
4. Real-Life Example (setTimeout)
function x() {
let i = 1;
setTimeout(function() {
console.log(i); // remembers i
}, 1000);
}
x(); // after 1 sec → 1
👉 Even after x() has finished, the callback inside setTimeout still remembers i.
5. Tricky Example – Closure in Loops
// Using var
for (var i = 1; i <= 3; i++) {
setTimeout(function() {
console.log(i);
}, i * 1000);
}
// Output: 4 4 4
// Using let
for (let i = 1; i <= 3; i++) {
setTimeout(function() {
console.log(i);
}, i * 1000);
}
// Output: 1 2 3
Why?
var→ function-scoped → all callbacks share samei, which becomes 4 after loop ends.let→ block-scoped → each iteration has its own copy ofi→ closures preserve separate values.
6. Closure in Interview Questions
Example 1 – Function Returning Function
function makeCounter() {
let count = 0;
return function() {
count++;
return count;
}
}
const counter1 = makeCounter();
console.log(counter1()); // 1
console.log(counter1()); // 2
const counter2 = makeCounter();
console.log(counter2()); // 1
👉 Each call to makeCounter() creates a new closure with its own count.
Example 2 – Closure with setTimeout in loop (Fixing var)
for (var i = 1; i <= 3; i++) {
(function(j) {
setTimeout(function() {
console.log(j);
}, j * 1000);
})(i);
}
// Output: 1 2 3
👉 We use an IIFE (Immediately Invoked Function Expression) to capture each value of i in a closure.
7. Use Cases of Closures
Data hiding / Encapsulation
function bankAccount(initialBalance) { let balance = initialBalance; return { deposit(amount) { balance += amount; }, getBalance() { return balance; } }; } const account = bankAccount(100); account.deposit(50); console.log(account.getBalance()); // 150setTimeout / async callbacks
Function factories
Memoization / caching
8. Visualization (Lexical Environment Chain)
Global LE
└── outer’s LE { a: 10 }
└── inner’s LE { }
👉 Even after outer finishes, inner still has reference to outer’s LE.
9. Takeaways ✅
Closure = function + its lexical environment.
Functions “carry their scope” wherever they go.
Used for data hiding, async handling, callbacks, memoization.
Important for interview trick Qs (loops, setTimeout, counters).