JavaScript調(diào)用堆棧及setTimeout使用方法深入剖析
setTimeout(function(){alert("Hello World");},1000);
會(huì)在執(zhí)行到這句話后延遲1秒鐘來(lái)彈出alert窗口。那么再看這一段:
function a(){
setTimeout(function() {alert(1)}, 0);
alert(2);
}
a();
注意這段代碼中的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ù)a的時(shí)候,a先入棧,如果不給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)度提供極大便利。
相關(guān)文章
對(duì)存在JavaScript隱式類型轉(zhuǎn)換的四種情況的總結(jié)(必看篇)
下面小編就為大家?guī)?lái)一篇對(duì)存在JavaScript隱式類型轉(zhuǎn)換的四種情況的總結(jié)(必看篇)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-08-08JS正則表達(dá)式實(shí)現(xiàn)字符串中連續(xù)在一起的字符去重
這篇文章主要給大家介紹了關(guān)于JS正則表達(dá)式實(shí)現(xiàn)字符串中連續(xù)在一起的字符去重的相關(guān)資料,學(xué)會(huì)正則表達(dá)式對(duì)開(kāi)發(fā)者而言是個(gè)非常有用的技能,很多功能可以簡(jiǎn)單的用一句正則來(lái)實(shí)現(xiàn),需要的朋友可以參考下2023-11-11JavaScript中函數(shù)表達(dá)式和函數(shù)聲明及函數(shù)聲明與函數(shù)表達(dá)式的不同
這篇文章主要介紹了JavaScript中函數(shù)表達(dá)式和函數(shù)聲明及函數(shù)聲明與函數(shù)表達(dá)式的不同的相關(guān)資料,需要的朋友可以參考下2015-11-11Ajax跨域?qū)崿F(xiàn)代碼(后臺(tái)jsp)
這篇文章主要介紹了Ajax跨域?qū)崿F(xiàn)代碼(后臺(tái)jsp),需要的朋友可以參考下2017-01-01微信小程序wx.previewImage預(yù)覽圖片實(shí)例詳解
下面通過(guò)實(shí)例代碼給大家講解了微信小程序wx.previewImage預(yù)覽圖片功能,需要的朋友可以參考下2017-12-12對(duì)setInterval在火狐和chrome切換標(biāo)簽產(chǎn)生奇怪的效果之探索,與解決方案!
其實(shí)這個(gè)問(wèn)題,已經(jīng)困擾我很近。就是切換瀏覽器標(biāo)簽之后,再等幾十秒的時(shí)間切換回來(lái)setInterval就亂了陣,過(guò)一會(huì)又正常了!IE瀏覽器就沒(méi)有這種奇怪的現(xiàn)象!2011-10-10解決eclipse中沒(méi)有js代碼提示的問(wèn)題
今天小編就為大家分享一篇解決eclipse中沒(méi)有js代碼提示的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-10-10教你用幾十行js實(shí)現(xiàn)很炫的canvas交互特效
HTML5中的大部分動(dòng)畫(huà)都是通過(guò)Canvas實(shí)現(xiàn),因?yàn)镃anvas就像一塊畫(huà)布,我們可以通過(guò)調(diào)用腳本在Canvas上繪制任意形狀,甚至是制作動(dòng)畫(huà),這篇文章主要給大家介紹了關(guān)于用幾十行js實(shí)現(xiàn)很炫的canvas交互特效的相關(guān)資料,需要的朋友可以參考下2021-11-11js實(shí)現(xiàn)彈窗居中的簡(jiǎn)單實(shí)例
下面小編就為大家?guī)?lái)一篇js實(shí)現(xiàn)彈窗居中的簡(jiǎn)單實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-10-10