亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

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

hizengzeng / 1025人閱讀

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

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

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

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

首先看:

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

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

這個顯然大家都知道結(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)

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

單線程

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

事件循環(huán)

任務分為兩類:

同步任務

異步任務

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

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

當指定的事件完成后,Event Table 將這個函數(shù)移入到事件隊列

主線程中的任務執(zhí)行完畢后,去任務隊列讀取對應的函數(shù),進入主線程執(zhí)行

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

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

例如:

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

首先 setTimeout進入Event Table

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

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

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

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

setInterval

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

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

Promise 和 process.nextTick(callback)

除了廣義的同步任務和異步任務之外,還有對任務更精細的劃分,分為:

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

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

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

用一段代碼來說明:

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

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

console.log("4");

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

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

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

下面遇到console,輸出4

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

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

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

好了了解了基本的原理之后,我們來看一個更復雜的:

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")
    })
})

不知道大家答案是什么?接下來我們來進行分析一下:

第一輪:

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

遇到第一個setTimeout()進入宏任務隊列

遇到Process.nextTick()進入微任務隊列

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

遇到第二個setTimeout,進入宏任務隊列

然后執(zhí)行兩個微任務

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

執(zhí)行then,輸出8

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

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

遇到Process.nextTick(),進入微任務隊列

遇到Promise立即執(zhí)行輸出4,then進入微任務隊列

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

執(zhí)行then,輸出5

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

原文地址:傳送門

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

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/97139.html

相關文章

  • 深入前端-徹底搞懂JS的運行機制

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

    luckyw 評論0 收藏0
  • 深入前端-徹底搞懂JS的運行機制

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

    jaysun 評論0 收藏0
  • 深入前端-徹底搞懂瀏覽器運行機制

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

    YPHP 評論0 收藏0
  • 深入前端-徹底搞懂瀏覽器運行機制

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

    Youngs 評論0 收藏0
  • 徹底搞懂瀏覽器Event-loop

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

    source 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<