2013-02-22 84 views
0

提起如何解释此行为?JavaScript提起怪异行为

for(var i = 0; i < 4; i++) { 
    setTimeout(function() { 
     alert("i is: " + i); 
    }, i * 200); 
} 

的这个输出是4,4,4,4。

这被用作在文献吊装经常的危险例子。有意义的是,后面的输出可能是4,因为i变量被绑定到函数作用域,并且在所有调用之间共享,并且在它们执行的时候,我将4完成for循环。然而,初始调用指定了一个0 * 200或0的超时时间,因此我认为这应该立即执行,而我仍然小于4.是什么原因导致该函数的所有输出为4?

+4

这并不是因为它与吊装无关。即使你通过'0'作为延迟,浏览器的最小延迟大约是10ms。 – 2013-02-22 19:18:30

+0

我认为,我一直在网上阅读的例子都是误导性的。即http://thecomputersarewinning.com/post/a-dangerous-example-of-javascript-hoisting/ – 2013-02-22 19:21:51

回答

1

它并不是因为它与吊装无关。

即使您通过0作为延迟,浏览器的最小延迟约为10ms。无论您传递什么延迟,该函数都不会立即执行。

MDN documentation

需要注意的是,如果函数或代码片段可直到那个叫setTimeout()的线程执行终止是很重要的。

因此,在调用任何回调之前,for循环已经终止。

相关问题:

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()调用的结果仍然相同。这是因为无论计划运行的任何异步代码如何,同步流程都会继续。

0

这四个调用在第一个定时器到期之前(以及匿名方法调用触发)在循环内设置setTimeout fire。因此,当它启动时,结果始终为4. setTimeout计时器延迟永远不能保证。