JavaScript · Closures · Junior · Debugging
Why does this print `3 3 3` instead of `0 1 2`, and how do you fix it? ```js for (var i = 0; i < 3; i++) { setTimeout(() => console.log(i), 0); } ```
Short Interview Answer
All callbacks close over the same function-scoped `var i`, which is `3` when they run. Use `let`, a factory, or `bind` to capture per-iteration values.
Detailed Explanation
`var i` is one binding for the loop. Each arrow closes over that binding. After the loop, `i === 3`, and the timers fire later, so all log `3`. With `let i`, each iteration gets a new binding (per ES2015 per-iteration semantics), so callbacks see 0, 1, 2. Alternatives: IIFE/`function(i){...}(i)` to copy the value, or `setTimeout(console.log, 0, i)`. This is one of the most common closure interview traps.
Example
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 0);
}
// 0 1 2Interview Tip
Explain *when* the callbacks run relative to the loop — timing is the key insight.
Common Mistake
Blaming `setTimeout` itself instead of shared mutable binding.