setTimeout函数异常输出求助:循环执行结果为何不符合预期?
Hey there! I totally get why this is confusing—let's break down exactly what's happening here and how to fix it so you get the output you expect.
The Root Cause
The problem boils down to two key JavaScript behaviors:
varhas function/global scope, not block scope: When you declareiwithvar, there's only oneivariable shared across the entire loop. Every iteration uses the same variable, not a new one per loop run.setTimeoutis asynchronous: All the callback functions you pass tosetTimeoutwon't execute until after the loop has finished running. By that time, the loop has already incrementedito4(since the loop stops wheni < arr.lengthis false, which is wheniequals 4), andarr[4]isundefinedbecause your array only has elements at indexes 0-3.
Fixes to Get Your Expected Output
Here are three straightforward ways to fix this:
1. Replace var with let (ES6+)
let has block-level scoping, which means a brand new i is created for each loop iteration. Each setTimeout callback will capture the unique i value from its iteration:
<html> <head></head> <body> <script> const arr = [10, 12, 15, 21]; for (let i = 0; i < arr.length; i++) { setTimeout(function() { console.log('Index: ' + i + ', element: ' + arr[i]); }, 3000); } </script> </body> </html>
2. Use an Immediately Invoked Function Expression (IIFE)
Before ES6, IIFEs were the standard way to create a new scope for each loop iteration. We pass the current i as an argument to the IIFE, which captures that value for the setTimeout callback:
<html> <head></head> <body> <script> const arr = [10, 12, 15, 21]; for (var i = 0; i < arr.length; i++) { (function(index) { setTimeout(function() { console.log('Index: ' + index + ', element: ' + arr[index]); }, 3000); })(i); } </script> </body> </html>
3. Iterate with forEach
The forEach method creates a new function scope for each element in the array, so each callback gets its own index and element values automatically:
<html> <head></head> <body> <script> const arr = [10, 12, 15, 21]; arr.forEach(function(element, index) { setTimeout(function() { console.log('Index: ' + index + ', element: ' + element); }, 3000); }); </script> </body> </html>
内容的提问来源于stack exchange,提问作者Deadpool

