成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

徹底搞懂JavaScript執(zhí)行機(jī)制

hizengzeng / 863人閱讀

摘要:徹底搞懂執(zhí)行機(jī)制首先我們大家都了解的是,是一門單線程語(yǔ)言,所以我們就可以得出是按照語(yǔ)句順序執(zhí)行的首先看這個(gè)顯然大家都知道結(jié)果,依次輸出,然而換一種這個(gè)時(shí)候再看代碼的順序執(zhí)行,輸出,,,。不過即使主線程為空,也是達(dá)不到的,根據(jù)標(biāo)準(zhǔn),最低是。

徹底搞懂JavaScript執(zhí)行機(jī)制

首先我們大家都了解的是,JavaScript 是一門單線程語(yǔ)言,所以我們就可以得出:

JavaScript 是按照語(yǔ)句順序執(zhí)行的

首先看:

let a = "1"
console.log(a)

let b = "2"
console.log(b)

這個(gè)顯然大家都知道結(jié)果,依次輸出1,2

然而換一種:

setTimeout(function() {
    console.log(1)
})

new Promise(function(resolve) {
    console.log(2)
    for(var i = 0;i< 10;i++){
        i === 10 && resolve()
    }
}).then(function() {
    console.log(3)
})
console.log(4)

這個(gè)時(shí)候再看代碼的順序執(zhí)行,輸出1,2, 3, 4。好了放到瀏覽器運(yùn)行一下,什么?輸出居然是 2, 4, 3,1。說(shuō)好的按順序執(zhí)行呢?下面就需要去了解一下 JavaScript 的執(zhí)行機(jī)制問題了。

單線程

首先JavaScript 是一門單線程的語(yǔ)言,在最新的HTML5 推出的 Web-worker,但是 JavaScript 是一個(gè)單線程的語(yǔ)言這一個(gè)核心還是沒有改變。所以,JavaScript 的多線程都是基于單線程模擬出來(lái)的。所以牢記 JavaScript 是單線程語(yǔ)言。

事件循環(huán)

任務(wù)分為兩類:

同步任務(wù)

異步任務(wù)

當(dāng)我們打開頁(yè)面時(shí),頁(yè)面的渲染就是一大堆同步任務(wù),而像加載圖片和音頻資源耗時(shí)的任務(wù),就是異步任務(wù)。時(shí)間循環(huán)的主要內(nèi)容就是:

當(dāng)任務(wù)進(jìn)入執(zhí)行棧的時(shí)候,判斷是同步任務(wù)還是異步任務(wù),如果是同步任務(wù),進(jìn)入主線程進(jìn)行執(zhí)行,異步進(jìn)入 Event Table 進(jìn)行注冊(cè)函數(shù)。

當(dāng)指定的事件完成后,Event Table 將這個(gè)函數(shù)移入到事件隊(duì)列

主線程中的任務(wù)執(zhí)行完畢后,去任務(wù)隊(duì)列讀取對(duì)應(yīng)的函數(shù),進(jìn)入主線程執(zhí)行

上述的過程不斷重復(fù),也就構(gòu)成了事件循環(huán)

其中js引擎存在一個(gè)監(jiān)控進(jìn)程,不斷檢查主線程執(zhí)行棧是否為空,一旦為空,就會(huì)去時(shí)間隊(duì)列那檢查有沒有等待被調(diào)用的函數(shù)。

例如:

setTimeout( function() {
    console.log(1)
}, 0)
console.log(2)

首先 setTimeout進(jìn)入Event Table

執(zhí)行console.log(2)

setTimeout執(zhí)行的函數(shù)進(jìn)入事件隊(duì)列

主線程從事件隊(duì)列讀取函數(shù)執(zhí)行

這也就是為什么即使設(shè)置setTimeout(fn, 0)函數(shù)也不會(huì)立即執(zhí)行的原因。不過即使主線程為空,0ms也是達(dá)不到的,根據(jù)HTML標(biāo)準(zhǔn),最低是4ms。

setInterval

還有一個(gè)與setTimeout類似的函數(shù),對(duì)于setInterval來(lái)說(shuō),是循環(huán)執(zhí)行。對(duì)于執(zhí)行順序來(lái)說(shuō),setInterval會(huì)每隔指定的時(shí)間將注冊(cè)的函數(shù)置入Event Queue,如果前面的任務(wù)耗時(shí)太久,那么同樣需要等待。

但是需要注意的一點(diǎn)是,對(duì)于setInterval(fn, ms)來(lái)說(shuō),他并不是每過ms執(zhí)行一次 ,而是每過 ms 會(huì)有fn進(jìn)入任務(wù)隊(duì)列。也就是說(shuō)如果setInterval 的回調(diào)函數(shù)的執(zhí)行事件如果超過延遲ms,那么就看不出來(lái)事件間隔了。

Promise 和 process.nextTick(callback)

除了廣義的同步任務(wù)和異步任務(wù)之外,還有對(duì)任務(wù)更精細(xì)的劃分,分為:

macro-task(宏任務(wù)):包括整體代碼script、setTimeout、setInterval

micro-task(微任務(wù)):Promise、process.nextTick

事件循環(huán)的順序,決定js代碼的執(zhí)行順序。進(jìn)入整體代碼(宏任務(wù))后,開始第一次循環(huán)。接著執(zhí)行所有的微任務(wù)。然后再次從宏任務(wù)開始,找到其中一個(gè)任務(wù)隊(duì)列執(zhí)行完畢,再執(zhí)行所有的微任務(wù)。

用一段代碼來(lái)說(shuō)明:

setTimeout(function() {
    console.log("1");
})

new Promise(function(resolve) {
    console.log("2");
    resolve()
}).then(function() {
    console.log("3");
})

console.log("4");

這段代碼作為宏任務(wù),開始第一次循環(huán)

先遇到setTimeout,那么它的回調(diào)函數(shù)進(jìn)入到宏任務(wù)事件隊(duì)列中

遇到Promise,Promise立即執(zhí)行,輸出2,then任務(wù)進(jìn)入到微任務(wù)事件隊(duì)列中

下面遇到console,輸出4

第一個(gè)宏任務(wù)結(jié)束,看微任務(wù)事件隊(duì)列,執(zhí)行then,輸出3

第一輪循環(huán)結(jié)束,看宏任務(wù)隊(duì)列中存在setTimeout的回調(diào)函數(shù)執(zhí)行,輸出1

所有結(jié)果為:2,4,3,1

好了了解了基本的原理之后,我們來(lái)看一個(gè)更復(fù)雜的:

console.log("1");

setTimeout(function() {
    console.log("2");
    process.nextTick(function() {
        console.log("3");
    })
    new Promise(function(resolve) {
        console.log("4");
        resolve();
    }).then(function() {
        console.log("5")
    })
})
process.nextTick(function() {
    console.log("6");
})
new Promise(function(resolve) {
    console.log("7");
    resolve();
}).then(function() {
    console.log("8")
})

setTimeout(function() {
    console.log("9");
    process.nextTick(function() {
        console.log("10");
    })
    new Promise(function(resolve) {
        console.log("11");
        resolve();
    }).then(function() {
        console.log("12")
    })
})

不知道大家答案是什么?接下來(lái)我們來(lái)進(jìn)行分析一下:

第一輪:

首先整段代碼作為一個(gè)宏任務(wù)進(jìn)入主線程,首先遇到console.log()輸出1

遇到第一個(gè)setTimeout()進(jìn)入宏任務(wù)隊(duì)列

遇到Process.nextTick()進(jìn)入微任務(wù)隊(duì)列

然后遇到Promise,立即執(zhí)行,輸出7,then被添加到微任務(wù)隊(duì)列

遇到第二個(gè)setTimeout,進(jìn)入宏任務(wù)隊(duì)列

然后執(zhí)行兩個(gè)微任務(wù)

執(zhí)行Process.nextTick()輸出6

執(zhí)行then,輸出8

這樣第一輪循環(huán)就徹底結(jié)束了,進(jìn)行第二輪事件循環(huán),也就是第一個(gè)setTimeout

首先遇到console.log(),輸出2

遇到Process.nextTick(),進(jìn)入微任務(wù)隊(duì)列

遇到Promise立即執(zhí)行輸出4,then進(jìn)入微任務(wù)隊(duì)列

然后執(zhí)行第一個(gè)微任務(wù),輸出3

執(zhí)行then,輸出5

這樣第二輪事件循環(huán)就結(jié)束了,最后執(zhí)行第二個(gè)setTimeout,第二個(gè)setTimeout和上面原理類似,也就不重復(fù)說(shuō)明了。所以最終結(jié)果是:1,7,6,8,2,4,3,5,9,11,10,12

原文地址:傳送門

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/97139.html

相關(guān)文章

  • 深入前端-徹底搞懂JS的運(yùn)行機(jī)制

    摘要:瀏覽器是多進(jìn)程的詳情看我上篇總結(jié)瀏覽器執(zhí)行機(jī)制的文章深入前端徹底搞懂瀏覽器運(yùn)行機(jī)制瀏覽器每打開一個(gè)標(biāo)簽頁(yè),就相當(dāng)于創(chuàng)建了一個(gè)獨(dú)立的瀏覽器進(jìn)程。執(zhí)行異步操作事件完成,回調(diào)函數(shù)進(jìn)入。主線程從讀取回調(diào)函數(shù)并執(zhí)行。 最近看了很多關(guān)于JS運(yùn)行機(jī)制的文章,每篇都獲益匪淺,但各有不同,所以在這里對(duì)這幾篇文章里說(shuō)的很精辟的地方做一個(gè)總結(jié),參考文章鏈接見最后。本文博客地址 了解進(jìn)程和線程 進(jìn)程是應(yīng)用...

    luckyw 評(píng)論0 收藏0
  • 深入前端-徹底搞懂JS的運(yùn)行機(jī)制

    摘要:瀏覽器是多進(jìn)程的詳情看我上篇總結(jié)瀏覽器執(zhí)行機(jī)制的文章深入前端徹底搞懂瀏覽器運(yùn)行機(jī)制瀏覽器每打開一個(gè)標(biāo)簽頁(yè),就相當(dāng)于創(chuàng)建了一個(gè)獨(dú)立的瀏覽器進(jìn)程。執(zhí)行異步操作事件完成,回調(diào)函數(shù)進(jìn)入。主線程從讀取回調(diào)函數(shù)并執(zhí)行。 最近看了很多關(guān)于JS運(yùn)行機(jī)制的文章,每篇都獲益匪淺,但各有不同,所以在這里對(duì)這幾篇文章里說(shuō)的很精辟的地方做一個(gè)總結(jié),參考文章鏈接見最后。本文博客地址 了解進(jìn)程和線程 進(jìn)程是應(yīng)用...

    jaysun 評(píng)論0 收藏0
  • 深入前端-徹底搞懂瀏覽器運(yùn)行機(jī)制

    摘要:當(dāng)這些異步任務(wù)發(fā)生的時(shí)候,它們將會(huì)被放入瀏覽器的事件任務(wù)隊(duì)列中去,等到運(yùn)行時(shí)執(zhí)行線程空閑時(shí)候才會(huì)按照隊(duì)列先進(jìn)先出的原則被一一執(zhí)行,但終究還是單線程。 瀏覽器是多進(jìn)程的 showImg(https://segmentfault.com/img/remote/1460000019706956?w=815&h=517); Browser進(jìn)程: 瀏覽器的主進(jìn)程(負(fù)責(zé)協(xié)調(diào)、主控),只有一個(gè)。 負(fù)...

    YPHP 評(píng)論0 收藏0
  • 深入前端-徹底搞懂瀏覽器運(yùn)行機(jī)制

    摘要:當(dāng)這些異步任務(wù)發(fā)生的時(shí)候,它們將會(huì)被放入瀏覽器的事件任務(wù)隊(duì)列中去,等到運(yùn)行時(shí)執(zhí)行線程空閑時(shí)候才會(huì)按照隊(duì)列先進(jìn)先出的原則被一一執(zhí)行,但終究還是單線程。 瀏覽器是多進(jìn)程的 showImg(https://segmentfault.com/img/remote/1460000019706956?w=815&h=517); Browser進(jìn)程: 瀏覽器的主進(jìn)程(負(fù)責(zé)協(xié)調(diào)、主控),只有一個(gè)。 負(fù)...

    Youngs 評(píng)論0 收藏0
  • 徹底搞懂瀏覽器Event-loop

    摘要:檢查宏任務(wù)隊(duì)列,發(fā)現(xiàn)有的回調(diào)函數(shù)立即執(zhí)行回調(diào)函數(shù)輸出。接著遇到它的作用是在后將回調(diào)函數(shù)放到宏任務(wù)隊(duì)列中這個(gè)任務(wù)在再下一次的事件循環(huán)中執(zhí)行。 為什么會(huì)寫這篇博文呢? 前段時(shí)間,和頭條的小伙伴聊天問頭條面試前端會(huì)問哪些問題,他稱如果是他面試的話,event-loop肯定是要問的。那天聊了蠻多,event-loop算是給我留下了很深的印象,原因很簡(jiǎn)單,因?yàn)橹拔覐奈瓷钊肓私膺^,如果是面試的時(shí)...

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

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

0條評(píng)論

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