What will be the output? (Closures)
This problem demonstrates closures and how let creates block-scoped bindings in loops.
Quick Navigation: Understanding Closures • let vs var in Loops • Closure Practical Applications
Understanding Closures
A closure is a function that has access to variables in its outer (enclosing) lexical scope, even after the outer function has returned.
The Closure in This Problem
function outer() {
let count = 0; // Outer scope variable
return function inner() {
count++; // Inner function accesses outer variable
console.log(count);
}
}The inner function forms a closure over count, maintaining access to it even after outer() has finished executing.
Execution Flow
1. outer() is called
2. count = 0 is initialized
3. Loop runs 5 times, creating 5 setTimeout callbacks
4. inner function is returned (with closure over count)
5. closureFunc() is called → increments count to 1, logs 1
Output: 1
About the setTimeout Callbacks
The setTimeout callbacks will execute later (after 1s, 2s, 3s, 4s, 5s), but they don't affect the immediate output of closureFunc().
Important: With let i, each loop iteration creates a new binding, so each setTimeout callback captures a different i value (1, 2, 3, 4, 5).
let vs var in Loops
With let (Block Scope)
for (let i = 1; i <= 5; i++) {
setTimeout(function() {
console.log(i); // Each callback sees different i: 1, 2, 3, 4, 5
}, i * 1000);
}Why? let creates a new binding for each iteration. Each setTimeout callback captures its own i value.
With var (Function Scope)
for (var i = 1; i <= 5; i++) {
setTimeout(function() {
console.log(i); // All callbacks see the same i: 6, 6, 6, 6, 6
}, i * 1000);
}Why? var has function scope, so there's only one binding shared across all iterations. By the time callbacks execute, the loop has finished and i = 6.
Visual Comparison
let i:
Iteration 1: i = 1 (new binding)
Iteration 2: i = 2 (new binding)
Iteration 3: i = 3 (new binding)
...
var i:
Iteration 1: i = 1 (same binding)
Iteration 2: i = 2 (same binding)
Iteration 3: i = 3 (same binding)
... (all share one i)Closure Practical Applications
1. Data Privacy
function createCounter() {
let count = 0; // Private variable
return {
increment: () => ++count,
decrement: () => --count,
getCount: () => count
};
}
const counter = createCounter();
counter.increment(); // 1
counter.increment(); // 2
counter.getCount(); // 2
// count is not directly accessible2. Function Factories
function multiplyBy(factor) {
return function(number) {
return number * factor;
};
}
const double = multiplyBy(2);
const triple = multiplyBy(3);
double(5); // 10
triple(5); // 153. Event Handlers
function setupButton(buttonId, clickCount) {
document.getElementById(buttonId).addEventListener('click', function() {
clickCount++;
console.log(`Button clicked ${clickCount} times`);
});
}Each button maintains its own clickCount through closure.