麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 編程 > JavaScript > 正文

你知道setTimeout是如何運(yùn)行的嗎?

2019-11-20 09:14:01
字體:
供稿:網(wǎng)友

大家看下如下代碼,猜猜執(zhí)行結(jié)果:

var start = new Date;setTimeout(function(){ console.log('時間流逝了:'+(new Date - start)+'毫秒');}, 200);while (new Date - start < 1000) {}console.log(1);function doSoming(){ setTimeout(function(){  console.log('時間又流逝了:'+(new Date - start)+'毫秒'); },10);}doSoming();while (new Date - start < 2000) {}console.log(2);

結(jié)果是:
約1秒后輸出:1,
再過約1秒后輸出:2,
接著才立即輸出:時間流逝了: 2002 毫秒
最后輸出:時間又流逝了: 2003 毫秒

您猜對了沒?
這里通過setTimeout來延遲執(zhí)行的函數(shù)都被推到最后才執(zhí)行了;
原理如下:

在現(xiàn)有瀏覽器環(huán)境中,Javascript執(zhí)行引擎是單線程的,主線程的語句和方法,會阻塞定時任務(wù)的運(yùn)行,在Javascript執(zhí)行引擎之外,存在一個任務(wù)隊列,當(dāng)在代碼中調(diào)用setTimeout()方法時,注冊的延時方法會掛到瀏覽器內(nèi)核其他模塊處理,當(dāng)延時方法到達(dá)觸發(fā)條件,即到達(dá)設(shè)置的延時時間時,該模塊再將要執(zhí)行的方法添加至該模塊的任務(wù)隊列中。這一過程與執(zhí)行引擎主線程獨立,執(zhí)行引擎在主線程方法執(zhí)行完畢,到達(dá)空閑狀態(tài)時,才會從該模塊的任務(wù)隊列中順序提取任務(wù)來執(zhí)行,這期間的時間,可能大于注冊任務(wù)時設(shè)置的延時時間;

瀏覽器在空閑狀態(tài)下,會不斷的嘗試從模塊的任務(wù)隊列中提取任務(wù),這稱為事件循環(huán)模型;

再回頭看下前面的代碼,第二個setTimeout()的延遲方法的延遲時間是10毫秒,比第一個要早觸發(fā)啊!為什么執(zhí)行結(jié)果卻在后面?因為它被之前的代碼阻塞了約1000.5~1001毫秒了(視瀏覽器的處理速度),等他掛到處理模塊,等到觸發(fā)時間添加進(jìn)任務(wù)隊列時,第一個setTimeout()的延遲方法早就被添加到模塊的任務(wù)隊了,而引擎主線程是按順序提取得,所以,你應(yīng)該懂了吧?

現(xiàn)在,如果把上面的while (new Date - start < 1000) {}改成while (new Date - start < 189) {}或者是while (new Date - start < 190) {},結(jié)果又是什么?我就不多說了!各刷新瀏覽器20遍,自己看結(jié)果吧!

而setInterval()方法和setTimeout()地位是相同的,調(diào)用setInterval()方法時,注冊的延時方法掛到模塊處理,每當(dāng)觸發(fā)時間到達(dá),就往任務(wù)隊列添加一次要執(zhí)行的方法;

下面來具體看看setTimeout的語法: 
var timeID = window.setTimeout(func,delay,[param1,param2,...]); 
var timeID = window.setTimeout(code,delay);
setTimeout和setInterval是Window對象的方法(可省略window),第二個之后的可選參數(shù)(IE9及舊版不支持)是傳遞給func的參數(shù),每次調(diào)用他們時都會返回一個數(shù)字ID(在瀏覽器中打印出來就只是個數(shù)字,而本人在webstorm中打印出來發(fā)現(xiàn)它實際是一個對象,有很多個屬性),這個ID保持著它對應(yīng)的setTimeout或setInterval的相關(guān)信息,主要用來在中模塊中和任務(wù)隊列中清除(或關(guān)閉)掉它們(用方法clearTimeout(ID)和clearInterval(ID))。
如果你需要向你的回調(diào)函數(shù)內(nèi)傳遞一個參數(shù)以下是兼容IE的寫法 

if (document.all && !window.setTimeout.isPolyfill) { var __nativeST__ = window.setTimeout; window.setTimeout = function (vCallback, nDelay, param1, param2,param3) { var aArgs = Array.prototype.slice.call(arguments, 2); return __nativeST__(vCallback instanceof Function ? function () {  vCallback.apply(null, aArgs); } : vCallback, nDelay); }; window.setTimeout.isPolyfill = true;}

一個常見的錯誤出現(xiàn)在循環(huán)中使用閉包 

for(var i =0; i <10; i++){ setTimeout(function(){  console.log(i);  },1000);} 

上面的代碼只會輸出數(shù)字 10 十次。為什么?閉包! 

當(dāng) console.log 被調(diào)用的時候,雖然匿名函數(shù)保持對外部變量 i 的引用,但此時 for循環(huán)已經(jīng)結(jié)束, i 的值被修改成了 10. 

為了得到想要的結(jié)果,需要在每次循環(huán)中創(chuàng)建變量 i 的拷貝。 

為了正確的獲得循環(huán)序號,最好使用 匿名包裹器(其實就是我們通常說的自執(zhí)行匿名函數(shù))。 

for(var i =0; i <10; i++){ (function(e){  setTimeout(function(){   console.log(e);   },1000); })(i);}

外部的匿名函數(shù)會立即執(zhí)行,并把 i 作為它的參數(shù),此時函數(shù)內(nèi) e 變量就擁有了 i 的一個拷貝。
 當(dāng)傳遞給 setTimeout 的匿名函數(shù)執(zhí)行時,它就擁有了對 e 的引用,而這個值是不會被循環(huán)改變的。
 有另一個方法完成同樣的工作;那就是從匿名包裝器中返回一個函數(shù)。這和上面的代碼效果一樣。 

for(var i =0; i <10; i++){ setTimeout((function(e){  return function(){   console.log(e);  } })(i),1000)}

還有一個重要應(yīng)用:函數(shù)節(jié)流(throttle)與函數(shù)去抖(debounce)
請看我從網(wǎng)上收集的一些資料:
JavaScript-性能優(yōu)化之函數(shù)節(jié)流(throttle)與函數(shù)去抖(debounce)

參考鏈接: 
https://developer.mozilla.org/zh-CN/docs/Web/API/Window/setTimeout 
http://www.alloyteam.com/2015/10/turning-to-javascript-series-from-settimeout-said-the-event-loop-model/#prettyPhoto

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持武林網(wǎng)。

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 毛片毛片免费看 | 一区二区免费看 | 黄色片免费在线 | 国产91精品一区二区麻豆亚洲 | 免费毛片免费看 | 一区二区三区日本在线观看 | 免费观看黄色一级视频 | 国产精品久久久乱弄 | 国产精品成人免费一区久久羞羞 | 精品国产一区二区三区免费 | 91精品国产777在线观看 | 国产三级在线视频观看 | 久久国产一级片 | 一级国产电影 | 色蜜桃av| 亚洲欧美国产精品va在线观看 | 成人羞羞在线观看网站 | 91成人免费电影 | 中文字幕视频在线播放 | 久久丝袜脚交足黄网站免费 | 国产精品高潮99久久久久久久 | 羞羞电影网| 天天艹综合| 中国a毛片| 午夜影院在线免费观看 | 福利四区 | 精品国产一区二区亚洲人成毛片 | 日本不卡一区二区三区在线观看 | 日韩毛片免费观看 | 精品亚洲视频在线观看 | 成人午夜视频在线观看 | 91九色精品国产 | 午夜视频成人 | 欧美在线观看黄色 | 在线观看视频亚洲 | 国产91丝袜在线播放 | 国产a级网站 | 国产精品成人一区二区三区吃奶 | 欧美性久久久 | 毛片一区二区三区四区 | 毛片免费在线 |