認(rèn)識(shí)延遲時(shí)間為0的setTimeout
更新時(shí)間:2008年05月16日 22:44:39 作者:
由 John Resig 的 How JavaScript Timers Work 可以知道,現(xiàn)有的 JavaScript 引擎是單線程處理任務(wù)的。它把任務(wù)放到隊(duì)列中,不會(huì)同步去執(zhí)行,必須在完成一個(gè)任務(wù)后才開(kāi)始另外一個(gè)任務(wù)。
讓我們看看我之前的文章:JavaScript的9個(gè)陷阱及評(píng)點(diǎn),在第 9 點(diǎn) Focus Pocus 中提到的問(wèn)題。原作者對(duì)這個(gè)認(rèn)識(shí)有所偏差,其實(shí)不只是 IE 的問(wèn)題,而是現(xiàn)有 JavaScript 引擎對(duì)于線程實(shí)現(xiàn)的問(wèn)題(關(guān)于線程,我的概念其實(shí)不多,如果不對(duì),希望讀者多多指教)。. 我們來(lái)看 1 和 2。如果你能看看源代碼,會(huì)發(fā)現(xiàn)我們的任務(wù)很簡(jiǎn)單,就是給文檔增加一個(gè) input 文本框,并聚焦和選中。請(qǐng)現(xiàn)在分別點(diǎn)擊一下,可以看到,1 并沒(méi)有能夠聚焦和選中,而 2 可以。它們之間的區(qū)別在于,在執(zhí)行:
input.focus();
input.select();
時(shí), 2 多了一個(gè)延遲時(shí)間為 0 的 setTimeout 的外圍函數(shù),即:
setTimeout(function(){
input.focus();
input.select();
}, 0);
按照 JavaScript: The Definitive Guide 5th 的 14.1 所說(shuō):
在實(shí)踐中,setTimeout 會(huì)在其完成當(dāng)前任何延宕事件的事件處理器的執(zhí)行,以及完成文檔當(dāng)前狀態(tài)更新后,告訴瀏覽器去啟用 setTimeout 內(nèi)注冊(cè)的函數(shù)。
其實(shí),這是一個(gè)把需要執(zhí)行的任務(wù)從隊(duì)列中跳脫的技巧?;氐角懊娴睦樱琂avaScript 引擎在執(zhí)行 onkeypress 時(shí),由于沒(méi)有多線程的同步執(zhí)行,不可能同時(shí)去處理剛創(chuàng)建元素的 focus 和 select 事件,由于這兩個(gè)事件都不在隊(duì)列中,在完成 onkeypress 后,JavaScript 引擎已經(jīng)丟棄了這兩個(gè)事件,正如你看到的例子 1 的情況。而在例子 2 中,由于setTimeout可以把任務(wù)從某個(gè)隊(duì)列中跳脫成為新隊(duì)列,因而能夠得到期望的結(jié)果。
這才是延遲事件為 0 的setTimeout的真正目的。在此,你可以看看例子 3,它的任務(wù)是實(shí)時(shí)更新輸入的文本,現(xiàn)在請(qǐng)?jiān)囋?,你?huì)發(fā)現(xiàn)預(yù)覽區(qū)域總是落后一拍,比如你輸 a, 預(yù)覽區(qū)并沒(méi)有出現(xiàn) a, 在緊接輸入 b 時(shí), a 才不慌不忙地出現(xiàn)。其實(shí)我們是有辦法讓預(yù)覽區(qū)跟輸入框同步地,在此我沒(méi)有給出答案,因?yàn)樯厦嫠f(shuō)的,就是解決思路,try it yourself!
input.focus();
input.select();
時(shí), 2 多了一個(gè)延遲時(shí)間為 0 的 setTimeout 的外圍函數(shù),即:
setTimeout(function(){
input.focus();
input.select();
}, 0);
按照 JavaScript: The Definitive Guide 5th 的 14.1 所說(shuō):
在實(shí)踐中,setTimeout 會(huì)在其完成當(dāng)前任何延宕事件的事件處理器的執(zhí)行,以及完成文檔當(dāng)前狀態(tài)更新后,告訴瀏覽器去啟用 setTimeout 內(nèi)注冊(cè)的函數(shù)。
其實(shí),這是一個(gè)把需要執(zhí)行的任務(wù)從隊(duì)列中跳脫的技巧?;氐角懊娴睦樱琂avaScript 引擎在執(zhí)行 onkeypress 時(shí),由于沒(méi)有多線程的同步執(zhí)行,不可能同時(shí)去處理剛創(chuàng)建元素的 focus 和 select 事件,由于這兩個(gè)事件都不在隊(duì)列中,在完成 onkeypress 后,JavaScript 引擎已經(jīng)丟棄了這兩個(gè)事件,正如你看到的例子 1 的情況。而在例子 2 中,由于setTimeout可以把任務(wù)從某個(gè)隊(duì)列中跳脫成為新隊(duì)列,因而能夠得到期望的結(jié)果。
這才是延遲事件為 0 的setTimeout的真正目的。在此,你可以看看例子 3,它的任務(wù)是實(shí)時(shí)更新輸入的文本,現(xiàn)在請(qǐng)?jiān)囋?,你?huì)發(fā)現(xiàn)預(yù)覽區(qū)域總是落后一拍,比如你輸 a, 預(yù)覽區(qū)并沒(méi)有出現(xiàn) a, 在緊接輸入 b 時(shí), a 才不慌不忙地出現(xiàn)。其實(shí)我們是有辦法讓預(yù)覽區(qū)跟輸入框同步地,在此我沒(méi)有給出答案,因?yàn)樯厦嫠f(shuō)的,就是解決思路,try it yourself!
相關(guān)文章
js eval函數(shù)使用,js對(duì)象和字符串互轉(zhuǎn)實(shí)例
下面小編就為大家?guī)?lái)一篇js eval函數(shù)使用,js對(duì)象和字符串互轉(zhuǎn)實(shí)例。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-03-03
javascript彈出一個(gè)層并增加一個(gè)覆蓋層
彈出一個(gè)層的js代碼,比較不錯(cuò)2008-10-10
uni-app分包項(xiàng)目實(shí)戰(zhàn)總結(jié)
在使用uniapp開(kāi)發(fā)過(guò)程中,隨著我們的代碼工程越來(lái)越大,必然會(huì)面臨一個(gè)問(wèn)題,就是打出來(lái)的包會(huì)越來(lái)越大,下面這篇文章主要給大家介紹了關(guān)于uni-app分包項(xiàng)目實(shí)戰(zhàn)的相關(guān)資料,需要的朋友可以參考下2022-04-04
JavaScript對(duì)象的四種創(chuàng)建方法
這篇文章主要介紹了JavaScript對(duì)象的四種創(chuàng)建方法,首先我們通過(guò)確定一個(gè)對(duì)象的屬性和方法展開(kāi)主題相關(guān)內(nèi)容,需要的小伙伴可以參考一下2022-08-08
js實(shí)現(xiàn)圖片上傳到服務(wù)器和回顯
這篇文章主要介紹了js實(shí)現(xiàn)圖片上傳到服務(wù)器和回顯,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-01-01
微信小程序?qū)崿F(xiàn)收藏與取消收藏切換圖片功能
這篇文章主要介紹了微信小程序?qū)崿F(xiàn)收藏與取消收藏切換圖片功能,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-08-08
Select標(biāo)簽下拉列表二級(jí)聯(lián)動(dòng)級(jí)聯(lián)實(shí)例代碼
這篇文章主要介紹了Select標(biāo)簽下拉列表二級(jí)聯(lián)動(dòng)級(jí)聯(lián)實(shí)例代碼,需要的朋友可以參考下2014-02-02

