吊装如何解释这种行为?
for(var i = 0; i < 4; i++) {
setTimeout(function() {
alert("i is: " + i);
}, i * 200);
}
这是4,4,4,4的输出。
这被用作文献中经常提升的危险例子。有意义的是,后面的输出可能是4,因为i变量绑定到函数作用域,因此在所有调用之间共享,并且当它们执行时,我将完成for循环。但是,初始调用指定超时0 * 200或0,因此我觉得这应该立即执行,而i仍然小于4.是什么导致此函数的所有输出都是4?
答案 0 :(得分:1)
不是因为它与吊装无关。
即使您将0
作为延迟传递,浏览器中的最小延迟也是大约10毫秒。无论你传递什么延迟,该功能都不会立即执行。
重要的是要注意,如果在调用
setTimeout()
的线程终止之前无法执行函数或代码片段。
因此,在调用任何回调之前,for
循环已经终止。
相关问题:
答案 1 :(得分:1)
“但是,初始调用指定超时0 * 200或0,因此我觉得这应该立即执行......”
可能会发生在可以利用多个线程的环境中,但在单线程环境中,当前的同步执行流将继续不受约束直到完成。
这意味着循环继续并在第一次setTimeout
回调发生之前完成。
即使你的循环完成了 10,000毫秒,循环也会被允许在第一次回调之前继续。
试试这个演示:
var start = Date.now();
for(var i = 0; i < 4; i++) {
// set up the first timeout
setTimeout(function() {
alert("i is: " + i);
}, i * 200);
while (Date.now() - start < 1000) ; // block for 1000 ms
}
设置完第一个setTimeout
后,我们会阻止1000毫秒。 alert()
调用的结果仍然相同。这是因为无论计划运行的任何异步代码如何,同步流程都会继续。
答案 2 :(得分:0)
在第一个计时器到期之前,四个调用在set循环中激活(并且匿名方法调用将触发)。因此,当它触发时,结果始终为4. setTimeout计时器延迟永远不会得到保证。