鍍金池/ 教程/ HTML/ 淺談 JavaScript 函數(shù)與棧
淺談 JavaScript 之事件綁定
淺談 javascript 中字符串 String 與數(shù)組 Array
淺談 javascript 中基本包裝類型
淺談 JavaScript Math 和 Number 對(duì)象
淺談 Javascript 的靜態(tài)屬性和原型屬性
淺談 JavaScript 中定義變量時(shí)有無(wú) var 聲明的區(qū)別
淺談 JavaScript Array 對(duì)象
淺談 JavaScript 函數(shù)參數(shù)的可修改性問(wèn)題
淺談 javascript 中的 instanceof 和 typeof
淺談 JavaScript 中 Date (日期對(duì)象),Math 對(duì)象
淺談 Javascript 執(zhí)行順序
淺談 javascript 函數(shù)屬性和方法
淺談 JavaScript 中面向?qū)ο蠹夹g(shù)的模擬
淺談 javascript 的原型繼承
淺談 javascript 事件取消和阻止冒泡
根據(jù)一段代碼淺談 Javascript 閉包
淺談 Javascript 面向?qū)ο缶幊?/span>
淺談 javascript 六種數(shù)據(jù)類型以及特殊注意點(diǎn)
淺談 Javascript 變量作用域問(wèn)題
淺談 javascript 函數(shù)內(nèi)部屬性
淺談 javascript 中自定義模版
淺談 JavaScript 字符集
淺談 javascript 面向?qū)ο缶幊?/span>
淺談 JavaScript 框架分類
淺談 JavaScript 中的 Math.atan() 方法的使用
淺談 Javascript 數(shù)組與字典
淺談 JavaScript 數(shù)據(jù)類型及轉(zhuǎn)換
淺談 javascript 的調(diào)試
淺談 Javascript 嵌套函數(shù)及閉包
淺談 javascript 回調(diào)函數(shù)
淺談 JavaScript Date 日期和時(shí)間對(duì)象
淺談 Javascript 中的 Function 與 Object
淺談 JavaScript 數(shù)據(jù)類型
淺談 javascript 中 this 在事件中的應(yīng)用
淺談 javascript 中的閉包
淺談 javascript 函數(shù)劫持
淺談 Javascript 中深復(fù)制
淺談 JavaScript 函數(shù)節(jié)流
淺談 JavaScript 中的 String 對(duì)象常用方法
淺談 JavaScript 事件的屬性列表
淺談 JavaScript 函數(shù)與棧
淺談 JavaScript 的事件
淺談 javascript 中的作用域
淺談 JavaScript 的執(zhí)行效率
淺談 Javascript 事件模擬
淺談 JavaScript function 函數(shù)種類
淺談 javascript 歸并方法
淺談 javascript 迭代方法
淺談 JavaScript 編程語(yǔ)言的編碼規(guī)范
淺談 JavaScript 實(shí)現(xiàn)面向?qū)ο笾械念?/span>
淺談 Javascript 鼠標(biāo)和滾輪事件
淺談 Javascript Base64 加密解密
淺談 Javascript 中勻速運(yùn)動(dòng)的停止條件
淺談 javascript 實(shí)現(xiàn)八大排序
淺談 javascript 的分號(hào)的使用
淺談 javascript 中 createElement 事件
淺談 javascript 的數(shù)據(jù)類型檢測(cè)
淺談 javascript 對(duì)象模型和 function 對(duì)象
淺談 Javascript 如何實(shí)現(xiàn)勻速運(yùn)動(dòng)
淺談 JavaScript 字符串與數(shù)組
淺談 javascript 面向?qū)ο蟪绦蛟O(shè)計(jì)
淺談 Javascript 事件處理程序的幾種方式

淺談 JavaScript 函數(shù)與棧

Javascript 中會(huì)經(jīng)常用到 setTimeout 來(lái)推遲一個(gè)函數(shù)的執(zhí)行,如:

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

會(huì)在執(zhí)行到這句話后延遲 1 秒鐘來(lái)彈出 alert 窗口。

那么再看這一段:

function test(){  
    setTimeout(function() {alert(1)}, 0);  
    alert(2);  
}  
test();  

注意這段代碼中的 setTimeout 延遲設(shè)為了 0,就是延遲 0 毫秒,貌似是不做任何延遲立刻執(zhí)行,即 1,2。但實(shí)際的執(zhí)行結(jié)果確是 2,1。為什么?這得從 Javascript 調(diào)用堆棧(call stack)和 setTimeout 的功能說(shuō)起。

首先,JavaScript 是單線程的,即同一時(shí)間只執(zhí)行一條代碼,所以每一個(gè) JavaScript 代碼執(zhí)行塊會(huì) “阻塞” 其它異步事件的執(zhí)行。其次,和其他的編程語(yǔ)言一樣,Javascript 中的函數(shù)調(diào)用也是通過(guò)堆棧實(shí)現(xiàn)的。在執(zhí)行函數(shù) test 的時(shí)候,test 先入棧,如果不給 alert(1)加 setTimeout,那么 alert(1)第 2 個(gè)入棧,最后是 alert(2)。但現(xiàn)在給 alert(1)加上 setTimeout 后,alert(1)就被加入到了一個(gè)新的堆棧中等待,并 “盡可能快” 的執(zhí)行。這個(gè)盡可能快就是指在 a 的堆棧完成后就立刻執(zhí)行,因此實(shí)際的執(zhí)行結(jié)果就是先 alert(2),再 alert(1)。在這里 setTimeout 實(shí)際上是讓 alert(1)脫離了當(dāng)前函數(shù)調(diào)用堆棧。

看下面一個(gè)例子:

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

這樣一段函數(shù)意圖是每輸入一個(gè)字符就把當(dāng)前 input 里的所有字符都 alert 出來(lái),但實(shí)際效果確是 alert 出按鍵之前的內(nèi)容。這里,我們就可以利用 setTimeout(0) 來(lái)實(shí)現(xiàn)。

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

這樣當(dāng) onkeydown 事件觸發(fā)的時(shí)候,alert 就被放入了下一個(gè)調(diào)用堆棧,一旦 onkeydown 事件觸發(fā)的堆棧關(guān)閉后就開(kāi)始執(zhí)行。當(dāng)然瀏覽器還有個(gè) onkeyup 事件也可以實(shí)現(xiàn)我們的需求。

這樣的 setTimeout 用法在實(shí)際項(xiàng)目中還是會(huì)時(shí)常遇到。比如瀏覽器會(huì)聰明的等到一個(gè)函數(shù)堆棧結(jié)束后才改變 DOM,如果再這個(gè)函數(shù)堆棧中把頁(yè)面背景先從白色設(shè)為紅色,再設(shè)回白色,那么瀏覽器會(huì)認(rèn)為 DOM 沒(méi)有發(fā)生任何改變而忽略這兩句話,因此我們可以通過(guò) setTimeout 把 “設(shè)回白色” 函數(shù)加入下一個(gè)堆棧,那么就可以確保背景顏色發(fā)生過(guò)改變了(雖然速度很快可能無(wú)法被察覺(jué))。

總之,setTimeout 增加了 Javascript 函數(shù)調(diào)用的靈活性,為函數(shù)執(zhí)行順序的調(diào)度提供極大便利。