国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

前端計(jì)劃——JavaScript中關(guān)于setTimeout的那些事

sihai / 2581人閱讀

摘要:需要注意的是,及更早的瀏覽器不支持第一種語(yǔ)法中向延遲函數(shù)傳遞額外參數(shù)的功能。如果在不改變遞歸模式的前提下修善這段代碼解決方案加入定時(shí)器題目四考察和系列解釋立即的對(duì)象,是在本輪事件循環(huán)的結(jié)束時(shí),而不是在下一輪事件循環(huán)的開始時(shí)。

前言:setTimeout是JavaScript中常見的一個(gè)window對(duì)象方法,本文將介紹關(guān)于它的一些基礎(chǔ)知識(shí)和易出錯(cuò)的地方。

1、基礎(chǔ)知識(shí)

作用:setTimeout() 方法用于在指定的毫秒數(shù)后調(diào)用函數(shù)或計(jì)算表達(dá)式。

基本語(yǔ)法:

let timeoutId = window.setTimeout(func[, delay, param1, params2, ...]);
let timeoutId = scope.setTimeout(code[, delay]);
let timeoutId = window.setTimeout(function, milliseconds);

timeoutID 是該延時(shí)操作的數(shù)字ID, 此ID隨后可以用來作為window.clearTimeout方法的參數(shù)。

func是你想要在delay毫秒之后執(zhí)行的函數(shù)。

code 在第二種語(yǔ)法,是指你想要在delay毫秒之后執(zhí)行的代碼字符串,(使用該語(yǔ)法是不推薦的,
不推薦的原因和eval()一樣,即:1、安全性差(可被植入惡意代碼)2、執(zhí)行效率低(需要將字符串解析為代碼再執(zhí)行))

delay 是延遲的毫秒數(shù)(1秒=1000毫秒),函數(shù)的調(diào)用會(huì)在該延遲之后發(fā)生。如果省略該參數(shù),delay取默認(rèn)值0。

需要注意的是,IE9 及更早的 IE 瀏覽器不支持第一種語(yǔ)法中向延遲函數(shù)傳遞額外參數(shù)的功能。

//以下是一個(gè)簡(jiǎn)單實(shí)例,3秒后彈窗提示
function myFunction(){
    setTimeout(function(){alert("Hello")},3000);
}
2、單線程與事件隊(duì)列機(jī)制

先來看一些程序

//請(qǐng)判斷以下代碼輸出結(jié)果
setTimeout(function(){
    alert("Hello World");
   },1000);
   while(true){};
//該函數(shù)會(huì)陷入死循環(huán),1秒后并不會(huì)彈出提醒
//請(qǐng)寫出以下代碼輸出結(jié)果
setTimeout(function (){
    console.log("a")
},0)
console.log("b")
//輸出結(jié)果為b,a

有同學(xué)可能會(huì)認(rèn)為:第一段代碼在1秒后會(huì)彈窗提示Hello World。而第二段代碼,把延遲毫秒數(shù)設(shè)為0,就會(huì)立即執(zhí)行,先輸出a,再輸出b。顯然,實(shí)際的結(jié)果不是這樣。

為什么呢?因?yàn)椋?/p>

JavaScript引擎是單線程運(yùn)行的,瀏覽器無論在什么時(shí)候都只且只有一個(gè)線程在運(yùn)行JavaScript程序。

我們先來介紹下瀏覽器渲染時(shí)的線程機(jī)制:
瀏覽器的內(nèi)核是多線程的,它們?cè)趦?nèi)核控制下相互配合以保持同步,一個(gè)瀏覽器至少實(shí)現(xiàn)三個(gè)常駐線程:JavaScript引擎線程,GUI渲染線程,瀏覽器事件觸發(fā)線程。

JavaScript引擎是基于事件驅(qū)動(dòng)單線程執(zhí)行的,JavaScript引擎一直等待著任務(wù)隊(duì)列中任務(wù)的到來,然后加以處理,瀏覽器無論什么時(shí)候都只有一個(gè)JavaScript線程在運(yùn)行JavaScript程序。

GUI渲染線程負(fù)責(zé)渲染瀏覽器界面,當(dāng)界面需要重繪(Repaint)或由于某種操作引發(fā)回流(Reflow)時(shí),該線程就會(huì)執(zhí)行。但需要注意,GUI渲染線程與JavaScript引擎是互斥的,當(dāng)JavaScript引擎執(zhí)行時(shí)GUI線程會(huì)被掛起,GUI更新會(huì)被保存在一個(gè)隊(duì)列中等到JavaScript引擎空閑時(shí)立即被執(zhí)行。

事件觸發(fā)線程,當(dāng)一個(gè)事件被觸發(fā)時(shí)該線程會(huì)把事件添加到待處理隊(duì)列的隊(duì)尾,等待JavaScript引擎的處理。這些事件可來自JavaScript引擎當(dāng)前執(zhí)行的代碼塊如setTimeout、也可來自瀏覽器內(nèi)核的其他線程如鼠標(biāo)點(diǎn)擊、Ajax異步請(qǐng)求等,但由于JavaScript的單線程關(guān)系所有這些事件都得排隊(duì)等待JavaScript引擎處理(當(dāng)線程中沒有執(zhí)行任何同步代碼的前提下才會(huì)執(zhí)行異步代碼)。
JavaScript引擎是基于事件驅(qū)動(dòng)單線程執(zhí)行的,JavaScript引擎一直等待著任務(wù)隊(duì)列中任務(wù)的到來,然后加以處理,瀏覽器無論什么時(shí)候都只有一個(gè)JavaScript線程在運(yùn)行JavaScript程序。

回歸開始的問題:

第一段代碼始終會(huì)執(zhí)行同步代碼,陷入死循環(huán),根本不會(huì)執(zhí)行setTimeout內(nèi)的函數(shù),也就不會(huì)彈窗。

第二段代碼,經(jīng)過查找資料,可以得知,setTimeout有一個(gè)最小執(zhí)行時(shí)間,當(dāng)指定的時(shí)間小于該時(shí)間時(shí),瀏覽器會(huì)用最小允許的時(shí)間作為setTimeout的時(shí)間間隔,也就是說——即使我們把setTimeout的毫秒數(shù)設(shè)置為0,被調(diào)用的程序也沒有馬上啟動(dòng),它仍然會(huì)放在事件隊(duì)列的最后。當(dāng)同步代碼執(zhí)行完,輸出b,然后再執(zhí)行延遲函數(shù),輸出a。

3、this

this是JavaScript中一個(gè)重要的考察點(diǎn),可以簡(jiǎn)單記為:this是指向函數(shù)執(zhí)行時(shí)的當(dāng)前對(duì)象,倘若沒有明確的當(dāng)前對(duì)象,它就是指向window的。

請(qǐng)看如下代碼

//求函數(shù)執(zhí)行結(jié)果
var a=1;
var obj={
    a:2,
    b:function(){
        setTimeout(function(){
            console.log(this.a);
        },2000);
        
    }
};
obj.b();
//函數(shù)輸出為1

由setTimeout()調(diào)用的代碼運(yùn)行在與所在函數(shù)完全分離的執(zhí)行環(huán)境上。這會(huì)導(dǎo)致,這些代碼中包含的 this 關(guān)鍵字會(huì)指向 window (或全局)對(duì)象,這和所期望的this的值是不一樣的。也就是當(dāng)執(zhí)行時(shí),this.a并不能讀取obj對(duì)象中的a,而是會(huì)找到全局對(duì)象的a,故輸出結(jié)果為1。
為了改變這種情況,有以下兩種方法

//方法一
var a=1;
var obj={
    var me = this;
    a:2,
    b:function(){
        setTimeout(function(){
            console.log(me.a);
        },2000);
        
    }
};
obj.b();
//方法二
var a=1;
var obj={
    a:2,
    b:function(){
        setTimeout(function(){
            console.log(this.a);
        }.bind(this),2000);
 
    }
};
obj.b();
4、混合知識(shí)點(diǎn)考察 題目一:求輸出結(jié)果
(function() {
    console.log(1); 
    setTimeout(function(){console.log(2)}, 1000); 
    setTimeout(function(){console.log(3)}, 0); 
    console.log(4);
})();
//輸出結(jié)果是1,4,3,2

解釋:參照第二部分的事件機(jī)制

題目二:對(duì)setTimeout和IIFE的考察

將 JavaScript 代碼包含在一個(gè)函數(shù)塊中有什么用途?為什么要這么做?
換句話說,為什么要用立即執(zhí)行函數(shù)表達(dá)式(Immediately-Invoked Function Expression)。
IIFE 有兩個(gè)比較經(jīng)典的使用場(chǎng)景,一是類似于在循環(huán)中定時(shí)輸出數(shù)據(jù)項(xiàng),二是類似于 JQuery/Node 的插件和模塊開發(fā)。

for(var i = 0; i < 5; i++) {
 setTimeout(function() {
 console.log(i); 
 }, 1000);
}
//輸出為5,5,5,5,5

使用IIFE

for(var i = 0; i < 5; i++) {
 (function(i) {
 setTimeout(function() {
 console.log(i); 
 }, 1000);
 })(i)
}
//輸出為0,1,2,3,4
題目三:setTimeout的分片應(yīng)用

如果 list 很大,下面的這段遞歸代碼會(huì)造成堆棧溢出。如果在不改變遞歸模式的前提下修善這段代碼?

var list = readHugeList();

var nextListItem = function() {
    var item = list.pop();
    if (item) {
    // process the list item...
    nextListItem();
    }
};

解決方案:加入定時(shí)器

var list = readHugeList();

var nextListItem = function() {
    var item = list.pop();
    if (item) {
    // process the list item...
    setTimeout(nextListItem(), 0);
    }
};
題目四:考察setTimeout和Promise系列
setTimeout(function () {
  console.log("three");
}, 0);

Promise.resolve().then(function () {
  console.log("two");
});

console.log("one");

// one
// two
// three

解釋:立即resolve的Promise對(duì)象,是在本輪“事件循環(huán)”(event loop)的結(jié)束時(shí),而不是在下一輪“事件循環(huán)”的開始時(shí)。上面代碼中,setTimeout(fn, 0)在下一輪“事件循環(huán)”開始時(shí)執(zhí)行,Promise.resolve()在本輪“事件循環(huán)”結(jié)束時(shí)執(zhí)行,console.log("one")則是立即執(zhí)行,因此最先輸出。

題目五:setTimeout與箭頭函數(shù)的this指向
function Timer() {
  this.s1 = 0;
  this.s2 = 0;
  // 箭頭函數(shù)
  setInterval(() => this.s1++, 1000);
  // 普通函數(shù)
  setInterval(function () {
    this.s2++;
  }, 1000);
}

var timer = new Timer();

setTimeout(() => console.log("s1: ", timer.s1), 3100);
setTimeout(() => console.log("s2: ", timer.s2), 3100);

上面代碼中,Timer函數(shù)內(nèi)部設(shè)置了兩個(gè)定時(shí)器,分別使用了箭頭函數(shù)和普通函數(shù)。前者的this綁定定義時(shí)所在的作用域(即Timer函數(shù)),后者的this指向運(yùn)行時(shí)所在的作用域(即全局對(duì)象)。所以,3100毫秒之后,timer.s1被更新了3次,而timer.s2一次都沒更新。

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

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

相關(guān)文章

  • JavaScript文章

    摘要:我對(duì)知乎前端相關(guān)問題的十問十答張?chǎng)涡駨場(chǎng)涡翊笊駥?duì)知乎上經(jīng)典的個(gè)前端問題的回答。作者對(duì)如何避免常見的錯(cuò)誤,難以發(fā)現(xiàn)的問題,以及性能問題和不好的實(shí)踐給出了相應(yīng)的建議。但并不是本身有問題,被標(biāo)準(zhǔn)定義的是極好的。 這一次,徹底弄懂 JavaScript 執(zhí)行機(jī)制 本文的目的就是要保證你徹底弄懂javascript的執(zhí)行機(jī)制,如果讀完本文還不懂,可以揍我。 不論你是javascript新手還是老...

    mumumu 評(píng)論0 收藏0
  • JS異步那些 一 (基礎(chǔ)知識(shí))

    摘要:異步那些事一基礎(chǔ)知識(shí)異步那些事二分布式事件異步那些事三異步那些事四異步那些事五異步腳本加載事件概念異步回調(diào)首先了講講中兩個(gè)方法和定義和用法方法用于在指定的毫秒數(shù)后調(diào)用函數(shù)或計(jì)算表達(dá)式。功能在事件循環(huán)的下一次循環(huán)中調(diào)用回調(diào)函數(shù)。 JS異步那些事 一 (基礎(chǔ)知識(shí))JS異步那些事 二 (分布式事件)JS異步那些事 三 (Promise)JS異步那些事 四(HTML 5 Web Workers...

    李濤 評(píng)論0 收藏0
  • 聊聊BOM那些

    摘要:如果省略該參數(shù),取默認(rèn)值該方法的返回值是一個(gè)正整數(shù),表示定時(shí)器的編號(hào)。 BOM BOM的全稱是Browser Object Model,被譯為瀏覽器對(duì)象模型BOM提供了獨(dú)立于HTML頁(yè)面內(nèi)容,而與瀏覽器相關(guān)的一系列對(duì)象,主要被用于管理瀏覽器窗口及與瀏覽器窗口之間通信等功能BOM由一系列對(duì)象構(gòu)成,這些對(duì)象可以簡(jiǎn)單理解為是由各個(gè)瀏覽器所提供的 Window對(duì)象 BOM中最核心的對(duì)象就是Wi...

    widuu 評(píng)論0 收藏0
  • 2018 淺談前端面試那些

    摘要:聲明的變量不得改變值,這意味著,一旦聲明變量,就必須立即初始化,不能留到以后賦值。 雖然今年沒有換工作的打算 但為了跟上時(shí)代的腳步 還是忍不住整理了一份最新前端知識(shí)點(diǎn) 知識(shí)點(diǎn)匯總 1.HTML HTML5新特性,語(yǔ)義化瀏覽器的標(biāo)準(zhǔn)模式和怪異模式xhtml和html的區(qū)別使用data-的好處meta標(biāo)簽canvasHTML廢棄的標(biāo)簽IE6 bug,和一些定位寫法css js放置位置和原因...

    LiuRhoRamen 評(píng)論0 收藏0
  • 2018 淺談前端面試那些

    摘要:聲明的變量不得改變值,這意味著,一旦聲明變量,就必須立即初始化,不能留到以后賦值。 雖然今年沒有換工作的打算 但為了跟上時(shí)代的腳步 還是忍不住整理了一份最新前端知識(shí)點(diǎn) 知識(shí)點(diǎn)匯總 1.HTML HTML5新特性,語(yǔ)義化瀏覽器的標(biāo)準(zhǔn)模式和怪異模式xhtml和html的區(qū)別使用data-的好處meta標(biāo)簽canvasHTML廢棄的標(biāo)簽IE6 bug,和一些定位寫法css js放置位置和原因...

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

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

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<