2013-02-22 77 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計時器延遲永遠不能保證。