2009-09-01 61 views
13

在JavaScript中,有沒有這兩者之間有什麼不同:MyFunction()vs window.setTimeout('MyFunction()',0)?

// call MyFunction normal way 

MyFunction(); 

// call MyFunction with setTimeout to 0 // 

window.setTimeout('MyFunction()', 0); 

我問的原因是因爲跨在那裏,如果我使用setTimeout(0)調用該函數的代碼只能局勢近日來了。 據我的理解,setTimeout(0)與直接調用函數完全一樣,因爲你沒有設置任何延遲。但從我看到它在代碼中是如何工作的,setTimeout(0)似乎最後被執行。

有人可以澄清究竟如何setTimeout(0)真正按照其他函數調用的順序調用嗎?

+1

http:// stackoverflow。com/questions/779379/why-does-settimeoutfn-0-sometimes-help – 2009-09-01 02:33:00

回答

17

setTimeout()始終會使JavaScript塊排隊等待執行。這是由什麼時候執行的問題,這是由提供的延遲決定的。 以延遲爲0的方式調用setTimeout()將導致JavaScript解釋器意識到它當前正忙(執行當前函數),並且解釋器將調度當前調用堆棧爲空時執行的腳本塊(除非還有其他腳本塊也在排隊)。

調用堆棧變空可能需要很長時間,這就是爲什麼你看到延遲執行。這主要是由於單個窗口上下文中JavaScript的單線程性質。

爲了完整起見,MyFunction()將立即執行該函數。將不涉及排隊。

PSJohn Resig has some useful notes on how the JavaScript timing mechanism works

PPS:只有當您使用setTimeout(fn(),0)時,您的代碼似乎「工作」的原因是因爲只有當前調用堆棧完成時,瀏覽器才能更新DOM。因此,下一個JavaScript塊會識別DOM更改,這在您的情況下很可能會發生。 setTimeout()回調總是創建一個新的調用堆棧。

3

我猜想超時只在頁面完全加載時纔開始,而只要一個普通的'MyFunction()'就會在處理完成後立即執行。

+1

這是正確的。無需猜測。 – 2009-09-01 02:29:15

+1

@Marius設置了一個測試頁面並嘗試它 - 內聯函數將在頂部觸發器聲明的setTimeout(0)之前一直觸發頁面。 – 2009-09-01 02:38:32

+0

試過了,你是對的,並刪除了我的評論,但不是在你看到它之前。 – Marius 2009-09-01 03:10:49

0

計時器會嘗試執行一次當前線程完成。這取決於你調用window.setTimeout()的位置。如果它位於javascript標記中,但不在函數內部,那麼一旦達到javascript標記的末尾,它就會被調用。例如:

<html> 
<script type="text/javascript"> 
setTimeout(function(){alert("hello")},0); 
var d=Number(new Date())+1000; 
while(Number(new Date())<d){ 

} 
alert("hi"); 
</script> 
</html> 

如果你調用從事件發生的歷史的結果,例如onload事件函數裏面的setTimeout的,那麼它會等到事件處理函數返回:

<html> 
<script type="text/javascript"> 
document.addEventListener("mousedown",function(){ 
    setTimeout(function(){alert("hello")},0); 
    var d=Number(new Date())+1000; 
    while(Number(new Date())<d){ 

    } 
    alert("hi"); 
}, true); 
</script> 
</html> 

這是不可能的在另一個線程運行時讓JavaScript中的一個線程等待。事件偵聽器將等到當前線程完成後纔開始運行。

唯一的例外是Web Workers,但它們運行在不同的文件中,並且它們之間進行通信的唯一方法是使用事件偵聽器,因此雖然可以在另一個正在工作時發送消息,但它不會收到該消息直到完成,或者它手動檢查消息。

+0

您所說的一切在一般意義上都是正確的(JavaScript是單線程的),但setTimeout(0)將在頁面加載時觸發,而不是在觸擊腳本塊結尾時觸發。 – 2009-09-01 02:37:31

相關問題