Hoisting and Execution Context
How do closures interact with setTimeout and loop variables?
for (var i = 0; i < 3; i++) {
setTimeout(function() { console.log(i); }, 1000);
}
This code will output `3, 3, 3` after 1 second. This example demonstrates the interaction between function closures, variable scope, and the asynchronous nature of `setTimeout`. The key points to understand are: 1. The variable `i` is declared with `var`, which has function scope (not block scope). 2. The loop runs quickly, creating three `setTimeout` calls with callbacks that will execute after 1 second. 3. By the time these callbacks execute, the loop has already completed and `i` has the value `3` (the value that terminated the loop condition `i < 3`). 4. All three callbacks reference the same `i` variable in their closure, and by the time they execute, that variable's value is `3`. This is a common gotcha in JavaScript. To get the expected behavior of logging `0, 1, 2`, you would need to either: 1. Use `let` instead of `var` to create a block-scoped variable for each iteration: `for (let i = 0; i < 3; i++)` 2. Create a new function scope for each iteration to capture the current value of `i`: `for (var i = 0; i < 3; i++) { (function(j) { setTimeout(function() { console.log(j); }, 1000); })(i); }` This example illustrates the importance of understanding variable scope and closures in JavaScript, especially when working with asynchronous code.