Closures
Closures are consistently the #1 most asked advanced JavaScript concept in interviews at all levels.
What is a Closure?
A closure is a function that remembers the variables from its outer (lexical) scope even after the outer function has finished executing.
function makeCounter() {
let count = 0;
return function() {
count++;
return count;
};
}
const counter = makeCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3
// 'count' is preserved in the closure
Classic Interview Trap: var in loops
// Problem: prints 5,5,5,5,5
for (var i = 0; i < 5; i++) {
setTimeout(() => console.log(i), 100);
}
// Fix 1: use let (block scoped)
for (let i = 0; i < 5; i++) {
setTimeout(() => console.log(i), 100); // 0,1,2,3,4
}
// Fix 2: IIFE closure
for (var i = 0; i < 5; i++) {
((j) => setTimeout(() => console.log(j), 100))(i);
}
Practical Use Cases
- Data privacy/encapsulation: hide internal state
- Factory functions: create customized functions
- Memoization: cache expensive results
- Event handlers: maintain context
- Module pattern: expose only public API