對JavaScript調(diào)用堆棧和setTimeout用法的深入研究
當(dāng)前位置:點晴教程→知識管理交流
→『 技術(shù)文檔交流 』
javascript中會經(jīng)常用到settimeout來推遲一個函數(shù)的執(zhí)行,如: settimeout(function(){alert("hello world");},1000);會在執(zhí)行到這句話后延遲1秒鐘來彈出alert窗口。那么再看這一段: 1 function a(){ 2 settimeout(function() {alert(1)}, 0); 3 alert(2); 4 } 5 a(); 注意這段代碼中的settimeout延遲設(shè)為了0,就是延遲0毫秒,貌似是不做任何延遲立刻執(zhí)行,即1,2。但實際的執(zhí)行結(jié)果確是2,1。為什么?這得從javascript調(diào)用堆棧(call stack)和settimeout的功能說起。 首先,javascript是單線程的,即同一時間只執(zhí)行一條代碼,所以每一個javascript代碼執(zhí)行塊會“阻塞”其它異步事件的執(zhí)行。其次,和其他的編程語言一樣,javascript中的函數(shù)調(diào)用也是通過堆棧實現(xiàn)的。在執(zhí)行函數(shù)a的時候,a先入棧,如果不給alert(1)加settimeout,那么alert(1)第2個入棧,最后是alert(2)。但現(xiàn)在給alert(1)加上settimeout后,alert(1)就被加入到了一個新的堆棧中等待,并“盡可能快”的執(zhí)行。這個盡可能快就是指在a的堆棧完成后就立刻執(zhí)行,因此實際的執(zhí)行結(jié)果就是先alert(2),再alert(1)。在這里settimeout實際上是讓alert(1)脫離了當(dāng)前函數(shù)調(diào)用堆棧??聪旅嬉粋€例子: <input name="input" onkeydown="alert(this.value)" type="text" value="a" /> 這樣一段函數(shù)意圖是每輸入一個字符就把當(dāng)前input里的所有字符都alert出來,但實際效果確是alert出按鍵之前的內(nèi)容。這里,我們就可以利用settimeout(0)來實現(xiàn)。 <input onkeydown="var me=this; settimeout(function(){alert(me.value)}, 0)" name="input" type="text" value="a" /> 這樣當(dāng)onkeydown事件觸發(fā)的時候,alert就被放入了下一個調(diào)用堆棧,一旦onkeydown事件觸發(fā)的堆棧關(guān)閉后就開始執(zhí)行。當(dāng)然瀏覽器還有個onkeyup事件也可以實現(xiàn)我們的需求。 這樣的settimeout用法在實際項目中還是會時常遇到。比如瀏覽器會聰明的等到一個函數(shù)堆棧結(jié)束后才改變dom,如果再這個函數(shù)堆棧中把頁面背景先從白色設(shè)為紅色,再設(shè)回白色,那么瀏覽器會認(rèn)為dom沒有發(fā)生任何改變而忽略這兩句話,因此我們可以通過settimeout把“設(shè)回白色”函數(shù)加入下一個堆棧,那么就可以確保背景顏色發(fā)生過改變了(雖然速度很快可能無法被察覺)。 總之,settimeout增加了javascript函數(shù)調(diào)用的靈活性,為函數(shù)執(zhí)行順序的調(diào)度提供極大便利。 該文章在 2010/3/24 21:59:36 編輯過 |
關(guān)鍵字查詢
相關(guān)文章
正在查詢... |