Problem Statement
What will this code output? for (var i = 0; i < 3; i++) { setTimeout(() => console.log(i), 0); }
Explanation
The output is 3, 3, 3 because of how var and closures work with setTimeout.
Var has function scope, not block scope. All three setTimeout callbacks share the same i variable.
The loop completes immediately, setting i to 3. Then the callbacks execute and all see i as 3.
This is a classic interview question testing understanding of scope, closures, and the event loop.
To fix it, use let instead of var, which creates a new i for each iteration with block scope.
Code Solution
SolutionRead Only
// Problem with var
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 0);
}
// Output: 3, 3, 3
// Why? The loop runs:
// i = 0, schedule callback
// i = 1, schedule callback
// i = 2, schedule callback
// i = 3, loop ends
// Now callbacks run and all see i = 3
// Solution 1: Use let (block scope)
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 0);
}
// Output: 0, 1, 2
// Solution 2: IIFE (Immediately Invoked Function Expression)
for (var i = 0; i < 3; i++) {
(function(j) {
setTimeout(() => console.log(j), 0);
})(i);
}
// Output: 0, 1, 2
// Solution 3: Pass parameter to setTimeout
for (var i = 0; i < 3; i++) {
setTimeout((num) => console.log(num), 0, i);
}
// Output: 0, 1, 2
// Understanding the event loop
console.log('Start');
setTimeout(() => console.log('Timeout'), 0);
Promise.resolve().then(() => console.log('Promise'));
console.log('End');
// Output: Start, End, Promise, Timeout
// (Microtasks run before macrotasks)