JavaScript中setTimeout为何在for循环结束后能执行指定次数?
关于setTimeout循环执行次数的疑问解析
示例代码
for (var index = 1; index <= 3; index++) { setTimeout(function() { console.log('after ' + index + ' second(s):' + index); }, index * 1000); }
实际输出
after 4 second(s):4 after 4 second(s):4 after 4 second(s):4 after 4 second(s):4
问题解析
核心要区分回调注册时机和回调执行时机:
- 循环的每一次迭代都会同步调用
setTimeout,每调用一次就会向浏览器的定时器任务队列中注册一个回调任务。这个注册动作是在循环运行过程中完成的,和回调函数什么时候执行没有关系。 - 你的循环执行了多少次,就会调用多少次
setTimeout,也就注册了多少个回调任务。等循环结束后,每个定时器的计时陆续到期,队列里的回调就会依次被执行,自然就会有对应次数的输出。 - 至于所有输出都是
4,是因为var声明的变量属于函数作用域,循环里的index是同一个全局/函数级变量。当回调执行时,循环已经结束,index的值已经自增到4(循环退出条件是index > 3),所有回调都引用了这个变量,所以输出结果一致。用let替代var时,每次循环迭代都会创建一个独立的index变量,每个回调引用的是当前迭代的变量,就能得到正确的计时数值。
内容的提问来源于stack exchange,提问作者Chris Chris
相关产品推荐
相关产品推荐

