成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

Javascript定時(shí)器那些事兒

Riddler / 2961人閱讀

摘要:一什么是定時(shí)器提供了一些原生方法來(lái)實(shí)現(xiàn)延時(shí)去執(zhí)行某一段代碼,下面來(lái)簡(jiǎn)單介紹一下設(shè)置一個(gè)定時(shí)器,在定時(shí)器到期后執(zhí)行一次函數(shù)或代碼段定時(shí)器延遲后執(zhí)行的函數(shù)延遲后執(zhí)行的代碼字符串,不推薦使用原理類似延遲的時(shí)間單位毫秒,默認(rèn)值為向延遲函數(shù)傳遞而外的

一、什么是定時(shí)器

JS提供了一些原生方法來(lái)實(shí)現(xiàn)延時(shí)去執(zhí)行某一段代碼,下面來(lái)簡(jiǎn)單介紹一下

setTimeout: 設(shè)置一個(gè)定時(shí)器,在定時(shí)器到期后執(zhí)行一次函數(shù)或代碼段

var timeoutId = window.setTimeout(func[, delay, param1, param2, ...]);
var timeoutId = window.setTimeout(code[, delay]);

timeoutId: 定時(shí)器ID

func: 延遲后執(zhí)行的函數(shù)

code: 延遲后執(zhí)行的代碼字符串,不推薦使用原理類似eval()

delay: 延遲的時(shí)間(單位:毫秒),默認(rèn)值為0

param1,param2: 向延遲函數(shù)傳遞而外的參數(shù),IE9以上支持

setInterval: 以固定的時(shí)間間隔重復(fù)調(diào)用一個(gè)函數(shù)或者代碼段

var intervalId = window.setInterval(func, delay[, param1, param2, ...]);
var intervalId = window.setInterval(code, delay);

intervalId: 重復(fù)操作的ID

func: 延遲調(diào)用的函數(shù)

code: 代碼段

delay: 延遲時(shí)間,沒(méi)有默認(rèn)值

setImmediate: 在瀏覽器完全結(jié)束當(dāng)前運(yùn)行的操作之后立即執(zhí)行指定的函數(shù)(僅IE10和Node 0.10+中有實(shí)現(xiàn)),類似setTimeout(func, 0)

var immediateId = setImmediate(func[, param1, param2, ...]);
var immediateId = setImmediate(func);

immediateId: 定時(shí)器ID

func: 回調(diào)

requestAnimationFrame: 專門為實(shí)現(xiàn)高性能的幀動(dòng)畫而設(shè)計(jì)的API,但是不能指定延遲時(shí)間,而是根據(jù)瀏覽器的刷新頻率而定(幀)

var requestId = window.requestAnimationFrame(func);

func: 回調(diào)

上面簡(jiǎn)單的介紹了四種JS的定時(shí)器,而本文將會(huì)主要介紹比較常用的兩種:setTimeoutsetInterval。

二、舉個(gè)栗子

基本用法

// 下面代碼執(zhí)行之后會(huì)輸出什么?
var intervalId, timeoutId;

timeoutId = setTimeout(function () {
    console.log(1);
}, 300);

setTimeout(function () {
    clearTimeout(timeoutId);
    console.log(2);
}, 100);

setTimeout("console.log("5")", 400);

intervalId = setInterval(function () {
    console.log(4);
    clearInterval(intervalId);
}, 200);

// 分別輸出: 2、4、5

setIntervalsetTimeout的區(qū)別?

// 執(zhí)行在面的代碼塊會(huì)輸出什么?
setTimeout(function () {
    console.log("timeout");
}, 1000);

setInterval(function () {
    console.log("interval")
}, 1000);

// 輸出一次 timeout,每隔1S輸出一次 interval

/*--------------------------------*/

// 通過(guò)setTimeout模擬setInterval 和 setInterval有啥區(qū)別么?
var callback = function () {
    if (times++ > max) {
        clearTimeout(timeoutId);
        clearInterval(intervalId);
    }

    console.log("start", Date.now() - start);
    for (var i = 0; i < 990000000; i++) {}
    console.log("end", Date.now() - start);
},
delay = 100,
times = 0,
max = 5,
start = Date.now(),
intervalId, timeoutId;

function imitateInterval(fn, delay) {
    timeoutId = setTimeout(function () {
        fn();

        if (times <= max) {
            imitateInterval(fn ,delay);
        }
    }, delay);
}

imitateInterval(callback, delay);
intervalId = setInterval(callback, delay);

如果是setTimeoutsetInterval的話,它倆僅僅在執(zhí)行次數(shù)上有區(qū)別,setTimeout一次、setIntervaln次。

而通過(guò)setTimeout模擬的setIntervalsetInterval的區(qū)別則在于:setTimeout只有在回調(diào)完成之后才會(huì)去調(diào)用下一次定時(shí)器,而setInterval則不管回調(diào)函數(shù)的執(zhí)行情況,當(dāng)到達(dá)規(guī)定時(shí)間就會(huì)在事件隊(duì)列中插入一個(gè)執(zhí)行回調(diào)的事件,所以在選擇定時(shí)器的方式時(shí)需要考慮setInterval的這種特性是否會(huì)對(duì)你的業(yè)務(wù)代碼有什么影響?

setTimeout(func, 0)setImmediate(func)誰(shuí)更快?(僅僅是好奇,才寫的這段測(cè)試)

console.time("immediate");
console.time("timeout");

setImmediate(() => {
    console.timeEnd("immediate");
});

setTimeout(() => {
    console.timeEnd("timeout");
}, 0);

Node.JS v6.7.0中測(cè)試發(fā)現(xiàn)setTimeout更早執(zhí)行

面試題

下面代碼運(yùn)行后的結(jié)果是什么?

// 題目一
var t = true;
 
setTimeout(function(){
    t = false;
}, 1000);
 
while(t){}
 
alert("end");

/*--------------------------------*/

// 題目二
for (var i = 0; i < 5; i++) {
    setTimeout(function () {
        console.log(i);
    }, 0);
}

/*--------------------------------*/

// 題目三
var obj = {
    msg: "obj",
    shout: function () {
        alert(this.msg);
    },
    waitAndShout: function() {
        setTimeout(function () {
            this.shout();
        }, 0);    
    }
};
obj.waitAndShout();

問(wèn)題答案會(huì)在后面解答

三、JS定時(shí)器的工作原理

在解釋上面問(wèn)題的答案之前我們先來(lái)了解一下定時(shí)器的工作原理,這里將用引用How JavaScript Timers Work中的例子來(lái)解釋定時(shí)器的工作原理,該圖為一個(gè)簡(jiǎn)單版的原理圖。

上圖中,左側(cè)數(shù)字代表時(shí)間,單位毫秒;左側(cè)文字代表某一個(gè)操作完成后,瀏覽器去詢問(wèn)當(dāng)前隊(duì)列中存在哪些正在等待執(zhí)行的操作;藍(lán)色方塊表示正在執(zhí)行的代碼塊;右側(cè)文字代表在代碼運(yùn)行過(guò)程中,出現(xiàn)哪些異步事件。該圖大致流程如下:

程序開始時(shí),有一個(gè)JS代碼塊開始執(zhí)行,執(zhí)行時(shí)長(zhǎng)約為18ms,在執(zhí)行過(guò)程中有3個(gè)異步事件觸發(fā),其中包括一個(gè)setTimeout、鼠標(biāo)點(diǎn)擊事件、setInterval

第一個(gè)setTimeout先運(yùn)行,延遲時(shí)間為10ms,稍后鼠標(biāo)事件出現(xiàn),瀏覽器在事件隊(duì)列中插入點(diǎn)擊的回調(diào)函數(shù),稍后setInterval運(yùn)行,10ms到達(dá)之后,setTimeout向事件隊(duì)列中插入setTimeout的回調(diào)

當(dāng)?shù)谝粋€(gè)代碼塊執(zhí)行完成后,瀏覽器查看隊(duì)列中有哪些事件在等待,他取出排在隊(duì)列最前面的代碼來(lái)執(zhí)行

在瀏覽器處理鼠標(biāo)點(diǎn)擊回調(diào)時(shí),setInterval再次檢查到到達(dá)延遲時(shí)間,他將再次向事件隊(duì)列中插入一個(gè)interval的回調(diào),以后每隔指定的延遲時(shí)間之后都會(huì)向隊(duì)列中插入一個(gè)回調(diào)

后面瀏覽器將在執(zhí)行完當(dāng)前隊(duì)頭的代碼之后,將再次取出目前隊(duì)頭的事件來(lái)執(zhí)行

這里只是對(duì)定時(shí)器的原理做一個(gè)簡(jiǎn)單版的描述,實(shí)際的處理過(guò)程比這個(gè)復(fù)雜。

四、題目答案

好啦,我們現(xiàn)在再來(lái)看看上面的面試題的答案。

第一題

alert永遠(yuǎn)都不會(huì)執(zhí)行,因?yàn)镴S是單線程的,且定時(shí)器的回調(diào)將在等待當(dāng)前正在執(zhí)行的任務(wù)完成后才執(zhí)行,而while(t) {}直接就進(jìn)入了死循環(huán)一直占用線程,不給回調(diào)函數(shù)執(zhí)行機(jī)會(huì)

第二題

代碼會(huì)輸出 5 5 5 5 5,理由同上,當(dāng)i = 0時(shí),生成一個(gè)定時(shí)器,將回調(diào)插入到事件隊(duì)列中,等待當(dāng)前隊(duì)列中無(wú)任務(wù)執(zhí)行時(shí)立即執(zhí)行,而此時(shí)for循環(huán)正在執(zhí)行,所以回調(diào)被擱置。當(dāng)for循環(huán)執(zhí)行完成后,隊(duì)列中存在著5個(gè)回調(diào)函數(shù),他們的都將執(zhí)行console.log(i)的操作,因?yàn)楫?dāng)前js代碼上中并沒(méi)有使用塊級(jí)作用域,所以i的值在for循環(huán)結(jié)束后一直為5,所以代碼將輸出5個(gè)5

第三題

這個(gè)問(wèn)題涉及到this的指向問(wèn)題,由setTimeout()調(diào)用的代碼運(yùn)行在與所在函數(shù)完全分離的執(zhí)行環(huán)境上. 這會(huì)導(dǎo)致這些代碼中包含的this關(guān)鍵字會(huì)指向window (或全局)對(duì)象,window對(duì)象中并不存在shout方法,所以就會(huì)報(bào)錯(cuò),修改方案如下:

var obj = {
    msg: "obj",
    shout: function () {
        alert(this.msg);
    },
    waitAndShout: function() {
        var self = this; // 這里將this賦給一個(gè)變量
        setTimeout(function () {
            self.shout();
        }, 0);    
    }
};
obj.waitAndShout();
五、需要注意的點(diǎn)

setTimeout有最小時(shí)間間隔限制,HTML5標(biāo)準(zhǔn)為4ms,小于4ms按照4ms處理,但是每個(gè)瀏覽器實(shí)現(xiàn)的最小間隔都不同

因?yàn)镴S引擎只有一個(gè)線程,所以它將會(huì)強(qiáng)制異步事件排隊(duì)執(zhí)行

如果setInterval的回調(diào)執(zhí)行時(shí)間長(zhǎng)于指定的延遲,setInterval將無(wú)間隔的一個(gè)接一個(gè)執(zhí)行

this的指向問(wèn)題可以通過(guò)bind函數(shù)、定義變量、箭頭函數(shù)的方式來(lái)解決

六、參考

MDN

How JavaScript Timers Work

JavaScript定時(shí)器與執(zhí)行機(jī)制解析

博客地址: ssh.today,歡迎關(guān)注

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/88180.html

相關(guān)文章

  • Event Loop 那些事兒

    摘要:消息隊(duì)列和事件循環(huán)異步過(guò)程中,工作線程在異步操作完成后需要通知主線程,那么這個(gè)通知機(jī)制是怎樣實(shí)現(xiàn)的呢答案是利用消息隊(duì)列和事件循環(huán)。 Event Loop 那些事兒 我們通常說(shuō) JavaScript 是單線程的,實(shí)際上是指在 JS 引擎中負(fù)責(zé)解釋和執(zhí)行 JS 代碼的線程只有一個(gè),一般成為主線程,在這種前提下,為了讓用戶的操作不存在阻塞感,前端 APP 的運(yùn)行需要依賴于大量的異步過(guò)程,所以...

    tyheist 評(píng)論0 收藏0
  • 跨域那些事兒

    摘要:什么是跨域我們先看下以下場(chǎng)景開啟兩個(gè)本地服務(wù)器,頁(yè)面為,其中嵌套了,頁(yè)面想使用頁(yè)面的數(shù)據(jù),例如調(diào)用它的方法,會(huì)報(bào)以下錯(cuò)誤如圖所示,,,譯為協(xié)議主機(jī)和端口號(hào)必須符合,否則,就是跨域。跨域的幾種常見方案同源策略的限制范圍有以下幾種和無(wú)法讀取。 什么是跨域 我們先看下以下場(chǎng)景:開啟兩個(gè)本地服務(wù)器,頁(yè)面A為localhost:9800,其中嵌套了iframeB localhost:9000,頁(yè)...

    nevermind 評(píng)論0 收藏0
  • 5分鐘了解JSON那些事兒

    摘要:簡(jiǎn)介是對(duì)象表示法的縮寫是一種數(shù)據(jù)格式而不是一種編程語(yǔ)言用來(lái)表示結(jié)構(gòu)化數(shù)據(jù)是的一個(gè)嚴(yán)格子集并不從屬于很多編程語(yǔ)言都可以用數(shù)據(jù)格式語(yǔ)法語(yǔ)法可以表示以下三種類型的值簡(jiǎn)單值字符串?dāng)?shù)值布爾值但是不支持對(duì)象數(shù)組不支持變量函數(shù)對(duì)象實(shí)例簡(jiǎn)單值字符串?dāng)?shù)字布爾 JSON 簡(jiǎn)介 JSON是JavaScript Object Notation(JavaScript對(duì)象表示法)的縮寫 JSON是一種數(shù)據(jù)格式,...

    ad6623 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<