定時(shí)器(setTimeout)的秘密

美美噠武功山

原文地址:→傳送門(mén)

寫(xiě)在前面

setTimeout()是大家再熟悉不過(guò)的定時(shí)器,但平時(shí)對(duì)定時(shí)器的了解甚少挖炬,于是想看看setTimeout()的原理機(jī)制。

setTimeout()基礎(chǔ)

setTimeout()函數(shù)用來(lái)指定某個(gè)函數(shù)或某段代碼怀樟,在多少毫秒之后執(zhí)行绽慈。它返回一個(gè)整數(shù),表示定時(shí)器的編號(hào)媒吗,以后可以用來(lái)取消這個(gè)定時(shí)器仑氛。

var timeer = setTimeout(function|code,delay);

注:其中為code時(shí)需要以字符串形式傳入,一般都是使用傳入function的形式闸英。

setTimeout(func,delay,arg1,arg2···)

setTimeout()可傳入多個(gè)參數(shù)锯岖,第三個(gè)參數(shù)起是作為回調(diào)函數(shù)的參數(shù)傳入。

        function add(a,b){
            console.log(a+b);
        }
        setTimeout(add,4000,20,30);  //20和30作為add的參數(shù)傳入 結(jié)果為50

HTML5規(guī)定setTimeout()的最短時(shí)間間隔是4ms甫何,對(duì)于不處在當(dāng)前窗口的頁(yè)面出吹,瀏覽器會(huì)將時(shí)間間隔擴(kuò)大到1000ms,若筆記本電腦處于電池供電狀態(tài)辙喂,chrome及IE9以上版本捶牢,會(huì)將時(shí)間間隔切換到系統(tǒng)定時(shí)器赃额,約15.6ms。

setTimeout()中回調(diào)函數(shù)的指向

setTimeout()回調(diào)函數(shù)調(diào)用的是某個(gè)對(duì)象的方法叫确,則其中this指向的是setTimeout所處的環(huán)境而并非指向該對(duì)象環(huán)境跳芳。

可使用ES5中的bind()方法解決this指向,即將對(duì)象環(huán)境綁定到要執(zhí)行的回調(diào)函數(shù)上即可竹勉。

        var name = 'lily';
        function Person(name){
            this.name = name;
            this.printName = function(){
                console.log(this.name);
            }
        }

        var person01 = new Person('jike');
        
         //此處的this.name為window下的name飞盆,所以是'lily'
        window.setTimeout(person01.printName,1000); 
        
        //此處將printName綁定在person01上,所以this.name的值為'jike'
        window.setTimeout(person01.printName.bind(person01),2000);  
        
        //將printName中的this.name與person01限定在同一個(gè)作用域中次乓,所以結(jié)果是'jike'
        window.setTimeout(function(){person01.printName();},3000); 
        
        //借助ES6中的箭頭函數(shù)也可以解決問(wèn)題
        window.setTimeout(() => {person01.printName},1000);   

setTimeout運(yùn)行機(jī)制

setTimeout()和setInterval()的運(yùn)行機(jī)制是吓歇,將指定的代碼移出本次執(zhí)行,等到下一輪Event Loop時(shí)票腰,再檢查是否到了指定時(shí)間城看。如果到了,就執(zhí)行對(duì)應(yīng)的代碼杏慰;如果不到测柠,就等到再下一輪Event Loop時(shí)重新判斷。這意味著缘滥,setTimeout()指定的代碼轰胁,必須等到本次執(zhí)行的所有代碼都執(zhí)行完,才會(huì)執(zhí)行朝扼。

例如:

task1();
setTimeout(otherTask,1000);
task2();

其中task1和task2為立即執(zhí)行任務(wù)赃阀,otherTask被指定在1s后執(zhí)行,此時(shí)otherTask被添加到任務(wù)隊(duì)列的尾部擎颖,要等當(dāng)前的腳本中Event Loop的任務(wù)隊(duì)列全部執(zhí)行完成后榛斯,才開(kāi)始執(zhí)行otherTask,但如果task1和task2很耗時(shí)搂捧,前面的任務(wù)超過(guò)1s還未結(jié)束驮俗,此時(shí)otherTask只能等task1和task2運(yùn)行結(jié)束,才會(huì)執(zhí)行otherTask异旧。

setTimeout(func,0)的運(yùn)用

當(dāng)延遲時(shí)間設(shè)為0時(shí)意述,即當(dāng)前任務(wù)隊(duì)列一結(jié)束就立即執(zhí)行func提佣。(換個(gè)角度說(shuō)就是同步任務(wù)的任務(wù)隊(duì)列結(jié)束后盡早執(zhí)行吮蛹。)

        task01();
        setTimeout(function(){
            console.log('hello!');  //在task01和task02結(jié)束后立即打印hello!
        },0)
        task02();

0ms在實(shí)際上是達(dá)不到的,根據(jù)HTML5標(biāo)準(zhǔn)拌屏,setTimeout()推遲執(zhí)行的時(shí)間最少是4ms潮针,如果小于這個(gè)值,會(huì)被自動(dòng)增加到4倚喂,同時(shí)也是為了防止多個(gè)setTimeout(func,0)語(yǔ)句連續(xù)執(zhí)行每篷,造成性能問(wèn)題瓣戚。

  • setTimeout(func,0)可以調(diào)整事件的發(fā)生順序。

clearTimeout()

setTimeout()和setInterval()函數(shù)焦读,都返回一個(gè)表示計(jì)數(shù)器編號(hào)的整數(shù)值子库,將該整數(shù)傳入clearTimeout()和clearInterval()函數(shù),就可以取消對(duì)應(yīng)的定時(shí)器矗晃。兩種定時(shí)器用的同一個(gè)編號(hào)池仑嗅。

setTimeout()和setInterval()函數(shù)返回的整數(shù)值都是連續(xù)的,因此可以利用循環(huán)來(lái)清除所有的定時(shí)器张症。

防抖動(dòng)(debounce)

該方法用于防止某個(gè)函數(shù)在短時(shí)間內(nèi)被密集調(diào)用仓技,具體來(lái)具體來(lái)說(shuō),debounce方法返回一個(gè)新版的該函數(shù)俗他,這個(gè)新版函數(shù)調(diào)用后脖捻,只有在指定時(shí)間內(nèi)沒(méi)有新的調(diào)用,才會(huì)執(zhí)行兆衅,否則就重新計(jì)時(shí)地沮。

實(shí)際中不要設(shè)置太多個(gè)setTimeout()和setInterval(),它們耗費(fèi)CPU,理想做法是將要延遲執(zhí)行的代碼都放在同一個(gè)函數(shù)里羡亩,然后支隊(duì)這個(gè)函數(shù)使用setTimeout()和setInterval()诉濒。

setInterval()

setInterval()使用原理機(jī)制與setTimeout()一樣,區(qū)別就是setInterval()是每隔多少ms執(zhí)行一次回調(diào)函數(shù)夕春。也可以傳入大于兩個(gè)參數(shù)未荒。

setInterval()指定的是“開(kāi)始執(zhí)行”之間的間隔,并不考慮每次任指定的是“開(kāi)始執(zhí)行”之間的間隔及志,并不考慮每次任片排,比如,setInterval()指定每100ms執(zhí)行一次速侈,每次執(zhí)行需要5ms率寡,那么第一次執(zhí)行后95ms后,第二次執(zhí)行就會(huì)開(kāi)始倚搬。如果某次執(zhí)行需要105ms冶共,即超過(guò)了delay時(shí)間,則執(zhí)行結(jié)束后下一次執(zhí)行就會(huì)立即開(kāi)始每界。

setInterval()的最短間隔是10ms捅僵,小于10ms的時(shí)間間隔會(huì)被調(diào)整到10ms

setInterval()具有累積效應(yīng),如果某個(gè)操作特別耗時(shí)眨层,超過(guò)了setInterval()的時(shí)間間隔庙楚,排在后面的操作就會(huì)被累積起來(lái),然后在很短的時(shí)間內(nèi)連續(xù)觸發(fā)趴樱,這可能會(huì)造成性能問(wèn)題馒闷。

資源參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末酪捡,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子纳账,更是在濱河造成了極大的恐慌逛薇,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,482評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件疏虫,死亡現(xiàn)場(chǎng)離奇詭異金刁,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)议薪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)尤蛮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人斯议,你說(shuō)我怎么就攤上這事产捞。” “怎么了哼御?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,762評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵坯临,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我恋昼,道長(zhǎng)看靠,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,273評(píng)論 1 279
  • 正文 為了忘掉前任液肌,我火速辦了婚禮挟炬,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘嗦哆。我一直安慰自己谤祖,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評(píng)論 5 373
  • 文/花漫 我一把揭開(kāi)白布老速。 她就那樣靜靜地躺著粥喜,像睡著了一般。 火紅的嫁衣襯著肌膚如雪橘券。 梳的紋絲不亂的頭發(fā)上额湘,一...
    開(kāi)封第一講書(shū)人閱讀 49,046評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音旁舰,去河邊找鬼锋华。 笑死,一個(gè)胖子當(dāng)著我的面吹牛鬓梅,可吹牛的內(nèi)容都是我干的供置。 我是一名探鬼主播谨湘,決...
    沈念sama閱讀 38,351評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼绽快,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼芥丧!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起坊罢,我...
    開(kāi)封第一講書(shū)人閱讀 36,988評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤续担,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后活孩,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體物遇,經(jīng)...
    沈念sama閱讀 43,476評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評(píng)論 2 324
  • 正文 我和宋清朗相戀三年憾儒,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了询兴。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,064評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡起趾,死狀恐怖诗舰,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情训裆,我是刑警寧澤眶根,帶...
    沈念sama閱讀 33,712評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站边琉,受9級(jí)特大地震影響属百,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜变姨,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評(píng)論 3 307
  • 文/蒙蒙 一族扰、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧定欧,春花似錦别伏、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,264評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至睦番,卻和暖如春类茂,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背托嚣。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,486評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工巩检, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人示启。 一個(gè)月前我還...
    沈念sama閱讀 45,511評(píng)論 2 354
  • 正文 我出身青樓兢哭,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親夫嗓。 傳聞我的和親對(duì)象是個(gè)殘疾皇子迟螺,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容