對JavaScript呼叫堆疊和setTimeout用法的深入研究

來源:互聯網
上載者:User

Javascript中會經常用到setTimeout來延遲一個函數的執行,如:

setTimeout(function(){alert("Hello World");},1000);

會在執行到這句話後延遲1秒鐘來彈出alert視窗。那麼再看這一段:

1 function a(){
2 setTimeout(function() {alert(1)}, 0);
3 alert(2);
4 }
5 a();    

注意這段代碼中的setTimeout延遲設為了0,就是延遲0毫秒,貌似是不做任何延遲立刻執行,即1,2。但實際的執行結果確是2,1。為什嗎?這得從Javascript呼叫堆疊(call stack)和setTimeout的功能說起。

首先,JavaScript是單線程的,即同一時間只執行一條代碼,所以每一個JavaScript代碼執行塊會“阻塞”其它非同步事件的執行。其次,和其他的程式設計語言一樣,Javascript中的函數調用也是通過堆棧實現的。在執行函數a的時候,a先入棧,如果不給alert(1)加setTimeout,那麼alert(1)第2個入棧,最後是alert(2)。但現在給alert(1)加上setTimeout後,alert(1)就被加入到了一個新的堆棧中等待,並“儘可能快”的執行。這個儘可能快就是指在a的堆棧完成後就立刻執行,因此實際的執行結果就是先alert(2),再alert(1)。在這裡setTimeout實際上是讓alert(1)脫離了當前函數呼叫堆疊。看下面一個例子:

<input name="input" onkeydown="alert(this.value)" type="text" value="a" />

這樣一段函數意圖是每輸入一個字元就把當前input裡的所有字元都alert出來,但實際效果確是alert出按鍵之前的內容。這裡,我們就可以利用setTimeout(0)來實現。

<input onkeydown="var me=this; setTimeout(function(){alert(me.value)}, 0)" name="input" type="text" value="a" />

這樣當onkeydown事件觸發的時候,alert就被放入了下一個呼叫堆疊,一旦onkeydown事件觸發的堆棧關閉後就開始執行。當然瀏覽器還有個onkeyup事件也可以實現我們的需求。

這樣的setTimeout用法在實際項目中還是會時常遇到。比如瀏覽器會聰明的等到一個函數堆棧結束後才改變DOM,如果再這個函數堆棧中把頁面背景先從白色設為紅色,再設回白色,那麼瀏覽器會認為DOM沒有發生任何改變而忽略這兩句話,因此我們可以通過setTimeout把“設回白色”函數加入下一個堆棧,那麼就可以確保背景顏色發生過改變了(雖然速度很快可能無法被察覺)。

總之,setTimeout增加了Javascript函數調用的靈活性,為函數執行順序的調度提供極大便利。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.