摘要:代碼大體上是自頂向下的,但中間穿插著有關(guān)渲染,事件回應(yīng)等異步代碼,他們將組成一個隊列,零秒延遲將會實現(xiàn)插隊操作。
js是單線程語言,但它允許通過設(shè)置超時值和間歇時間值來調(diào)度代碼在特定的時刻執(zhí)行。setTimeout是在指定delay時間后,將指定方法作為異步任務(wù)添加到異步任務(wù)隊列中,而setInterval則是可以循環(huán)地每隔一個delay就向異步任務(wù)隊列中添加一個任務(wù)
語法 setTimeout// 返回唯一的ID let timeoutID = window.setTimeout(func[, delay, param1, param2, ...]); let timeoutID = window.setTimeout(code[, delay]);setInterval
// 返回唯一的ID let intervalID = window.setInterval(func, delay[, param1, param2, ...]); let intervalID = window.setInterval(code, delay);clearTimeout和clearInterval
window.clearTimeout(timeoutID) window.clearInterval(intervalID)
timeoutID/intervalID 可以用來作為clearTimeout/clearInterval方法的參數(shù)
func是在delay毫秒之后執(zhí)行的函數(shù)
code 在第二種語法,是指你想要在delay毫秒之后執(zhí)行的代碼字符串 (使用該語法是不推薦的, 不推薦的原因和eval()一樣)
delay 是延遲的毫秒數(shù) (一秒等于1000毫秒),函數(shù)的調(diào)用會在該延遲之后發(fā)生。如果省略該參數(shù),delay取默認值0。實際的延遲時間可能會比 delay 值長,原因看下面的介紹。此外,根據(jù)w3c文檔得知,當(dāng)delay小于0的時候,delay按0來計算
setTimeout 和setInterval的使用方法類似,重點以setTimeout為例,有差異的地方再多帶帶分析。
例子1、比較一下下面兩個函數(shù)的區(qū)別
setTimeout(function () { func1() }, 0) setTimeout(function () { func1() })
0秒延遲,此回調(diào)將會放到一個能立即執(zhí)行的時段進行觸發(fā)。javascript代碼大體上是自頂向下的,但中間穿插著有關(guān)DOM渲染,事件回應(yīng)等異步代碼,他們將組成一個隊列,零秒延遲將會實現(xiàn)插隊操作。不寫第二個參數(shù),瀏覽器自動配置時間,在IE,F(xiàn)ireFox中,第一次配可能給個很大的數(shù)字,100ms上下,往后會縮小到最小時間間隔,Safari,chrome,opera則多為10ms上下。
---出自《javascript框架設(shè)計》
如果對0s的例子不明白,不要緊,我們繼續(xù)看下面這個:
var arr = [1,2,3]; for(var i in arr){ setTimeout(function(){console.log(arr[i])},0); console.log(arr[i]); }
控制臺會打印什么?
1 2 3 3 //3次
雖然setTimeout函數(shù)在每次循環(huán)的開始就調(diào)用了,但是卻被放到循環(huán)結(jié)束才執(zhí)行,循環(huán)結(jié)束,i=3,接著連續(xù)打印了3次3。
這里涉及到了js單線程執(zhí)行的問題:js在瀏覽器中是單線程執(zhí)行的,必須在完成當(dāng)前任務(wù)后才執(zhí)行隊列中的下一個任務(wù)。此外對于js還維護著一個setTimeout隊列,未執(zhí)行的setTimeout任務(wù)就按先后順序排在隊列中,等到主線程的普通任務(wù)隊列執(zhí)行完后,主線程就按順序執(zhí)行積累在setTimeout中的任務(wù)。所以上面的問題會先打印1、2、3.最后才打印3個3。
此時就有個疑問了,設(shè)置delay為0,而實際是大于0才執(zhí)行的,何必呢?
實際上這里我們主要用來改變?nèi)蝿?wù)的執(zhí)行順序,因為瀏覽器會在執(zhí)行完當(dāng)前任務(wù)隊列中的任務(wù),再執(zhí)行setTimeout隊列中積累的任務(wù)。通過設(shè)置任務(wù)在延遲到0s后執(zhí)行,就能改變?nèi)蝿?wù)執(zhí)行的先后順序,延遲該任務(wù)發(fā)生,使之異步執(zhí)行。
2、delay后可以傳遞第三個及多個參數(shù)。
for (var i = 1; i < 4; i++) { var t = setTimeout(function(i) { console.log(i); // 2. 1 4.2 console.log(t); // 3. 3 5.3 clearTimeout(t); }, 10, i); } console.log(i);
控制臺會打印什么?
4 1 3 2 3
此處在每次循環(huán)中,都將i作為回調(diào)函數(shù)的參數(shù)i傳入,第一次傳入1,第二次傳入2,第三次傳入3。第四次不滿足循環(huán)條件,跳出循環(huán),然后執(zhí)行console.log(i)。主線程執(zhí)行完當(dāng)前任務(wù)隊里的任務(wù),然后開始執(zhí)行seTimeout的隊列。此時t為setTimeout最后的返回ID值3,則一次打印1,3 2,3。因為clearTimeout清楚了id為3的延時任務(wù),所以只執(zhí)行了兩次。故一次打印41323
僅IE不支持第三個及以上參數(shù)
3、關(guān)于this指向的問題
myArray = ["zero", "one", "two"]; myArray.myMethod = function (sProperty) { alert(arguments.length > 0 ? this[sProperty] : this); }; myArray.myMethod(); // prints "zero,one,two" myArray.myMethod(1); // prints "one" setTimeout(myArray.myMethod, 1000); // prints "[object Window]" after 1 second setTimeout(myArray.myMethod, 1500, "1"); // prints "undefined" after 1,5 seconds
由setTimeout()調(diào)用的代碼運行在與所在函數(shù)完全分離的執(zhí)行環(huán)境上. 這會導(dǎo)致,這些代碼中包含的 this 關(guān)鍵字會指向 window (或全局)對象,這和所期望的this的值是不一樣的
如何解決this指向不確定的問題,我們可以用Function.prototype.bind()方法。
myArray = ["zero", "one", "two"]; myBoundMethod = (function (sProperty) { console.log(arguments.length > 0 ? this[sProperty] : this); }).bind(myArray); myBoundMethod(); // prints "zero,one,two" because "this" is bound to myArray in the function myBoundMethod(1); // prints "one" setTimeout(myBoundMethod, 1000); // still prints "zero,one,two" after 1 second because of the binding setTimeout(myBoundMethod, 1500, "1"); // prints "one" after 1.5 seconds應(yīng)用
1、替換setInterval來實現(xiàn)重復(fù)定時
2、防止事件瘋狂觸發(fā)
3、IE下重新播放單次gif動畫
4、blur事件延時生效
[https://html.spec.whatwg.org/...
[http://imweb.io/topic/56ac67f...
[https://developer.mozilla.org...
[http://www.cnblogs.com/suspid...
[https://johnresig.com/blog/ho...
[http://www.cnblogs.com/snandy...
[http://www.ruanyifeng.com/blo...
[http://www.cnblogs.com/silin6...
文章地址:[http://17biu.cn/2017/07/18/se...
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/84113.html
摘要:后續(xù)的一些輔助性優(yōu)化讀者可以自己琢磨,如函數(shù)指向,返回值保存等。 原文:https://keelii.github.io/2016/06/11/javascript-throttle/ 在瀏覽器 DOM 事件里面,有一些事件會隨著用戶的操作不間斷觸發(fā)。比如:重新調(diào)整瀏覽器窗口大?。╮esize),瀏覽器頁面滾動(scroll),鼠標移動(mousemove)。也就是說用戶在觸發(fā)這些瀏覽...
摘要:方法描述周期性地調(diào)用一個函數(shù)或者執(zhí)行一段代碼。方法可取消由方法設(shè)置的。語法詳解是該延時操作的數(shù)字此隨后可以用來作為方法的參數(shù)。需要注意的是,不支持第一種語法中向延遲函數(shù)傳遞額外參數(shù)的功能。該值標識要取消的延遲執(zhí)行代碼塊。 方法 描述 setInterval 周期性地調(diào)用一個函數(shù)(function)或者執(zhí)行一段代碼。 clearInterval 取消掉用setI...
摘要:在元素被插入之前生效,在元素被插入之后的下一幀移除。在整個進入過渡的階段中應(yīng)用,在元素被插入之前生效,在過渡動畫完成之后移除。這個類可以被用來定義進入過渡的過程時間,延遲和曲線函數(shù)。版及以上定義進入過渡的結(jié)束狀態(tài)。 基本概念 Vue 在插入、更新或者移除 DOM 時,提供多種不同方式的應(yīng)用過渡效果 在 CSS 過渡和動畫中自動應(yīng)用 class 可以配合使用第三方 CSS 動畫庫,如...
摘要:在元素被插入之前生效,在元素被插入之后的下一幀移除。在整個進入過渡的階段中應(yīng)用,在元素被插入之前生效,在過渡動畫完成之后移除。這個類可以被用來定義進入過渡的過程時間,延遲和曲線函數(shù)。版及以上定義進入過渡的結(jié)束狀態(tài)。 基本概念 Vue 在插入、更新或者移除 DOM 時,提供多種不同方式的應(yīng)用過渡效果 在 CSS 過渡和動畫中自動應(yīng)用 class 可以配合使用第三方 CSS 動畫庫,如...
閱讀 3160·2021-10-08 10:04
閱讀 1102·2021-09-30 09:48
閱讀 3470·2021-09-22 10:53
閱讀 1690·2021-09-10 11:22
閱讀 1702·2021-09-06 15:00
閱讀 2158·2019-08-30 15:56
閱讀 721·2019-08-30 15:53
閱讀 2293·2019-08-30 13:04