What is a Closure?
A closure is a function bundled together with its lexical environment—the variables that were in scope when the function was created. This allows the inner function to "remember" and access those variables even after the outer function has returned.
How Closures Work
When a function is defined inside another function, it forms a closure by capturing variables from the outer scope:
function createCounter() {
let count = 0; // This variable is "enclosed"
return function() {
count++; // Inner function accesses outer variable
return count;
};
}
const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3
The inner function maintains a reference to count even after createCounter() has finished executing.
Common Use Cases
1. Data Privacy / Encapsulation
function createBankAccount(initialBalance) {
let balance = initialBalance; // Private variable
return {
deposit: (amount) => { balance += amount; },
withdraw: (amount) => { balance -= amount; },
getBalance: () => balance
};
}
const account = createBankAccount(100);
account.deposit(50);
console.log(account.getBalance()); // 150
// balance is not directly accessible
2. Function Factories
function multiply(factor) {
return (number) => number * factor;
}
const double = multiply(2);
const triple = multiply(3);
console.log(double(5)); // 10
console.log(triple(5)); // 15
3. Event Handlers with State
function setupButton(buttonId) {
let clickCount = 0;
document.getElementById(buttonId).addEventListener("click", () => {
clickCount++;
console.log(`Clicked ${clickCount} times`);
});
}
Python Closures
def make_multiplier(n):
def multiplier(x):
return x * n # n is captured from outer scope
return multiplier
double = make_multiplier(2)
print(double(5)) # 10
Closures vs Classes
| Aspect | Closures | Classes |
|---|---|---|
| Syntax | Lighter, functional | More verbose |
| State | Implicitly captured | Explicit with self |
| Memory | One closure per instance | Shared methods |
| Use case | Simple state, callbacks | Complex objects |
Common Pitfalls
Loop Variable Capture
// Problem: All functions share the same i
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100);
}
// Prints: 3, 3, 3
// Solution: Use let (block scope) or IIFE
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100);
}
// Prints: 0, 1, 2
Memory Considerations
Closures keep their enclosed variables alive, which can lead to memory leaks if not managed properly. Variables in a closure won't be garbage collected until the closure itself is no longer referenced.