面試經典:Event Loop

歡迎關注 jsliang 的文檔庫 —— 一個窮盡一輩子更新的倉庫,查看更多技術、理財、健身文章:github.com/LiangJunron…html

一 目錄

不折騰的前端,和鹹魚有什麼區別前端

目錄
一 目錄
二 前言
三 Event Loop
四 瀏覽器 Event Loop
4.1 示例 1
4.2 示例 2
4.3 示例 3
4.4 小結
五 Node.js Event Loop
5.1 setTimeout & setImmediate
5.2 process.nextTick()
5.3 示例 1
5.4 示例 2
5.5 小結
六 總結
七 參考文獻

二 前言

返回目錄node

Hello 小夥伴們早上好、中午好、下午好、晚上好、凌晨好~git

在平常工做中,你有沒有碰到過這種疑惑:程序員

  • 疑惑一:爲何這份代碼它不按照個人意思走?爲啥不是輸出 1 2 3
for (var i = 0; i < 3; i++) {
  setTimeout(() => {
    console.log(i);
  }, 1000);
}
// console:
// 3
// 3
// 3
複製代碼
  • 疑惑二:爲何這份代碼它也不按照個人意思走?爲啥不是輸出 jsliang
let name;

setTimeout(() => {
  name = '梁峻榮';
  console.log(name);
}, 1000);

if (name) {
  name = 'jsliang';
  console.log(name);
}
// console: '梁峻榮'
複製代碼

孩子沒娘,說來話長。es6

既然說來話長,jsliang 只能嘗試長話短說了:github

  • 本篇文章從 Event Loop 原由提及,經過探討 瀏覽器環境 Event Loop 和 Node.js 環境 Event Loop,從而解惑工做中產生的困擾,擴展你面試知識點。

這麼一說,咱也好對文章進行劃分了:web

  • 第三章 Event Loop:解釋 Event Loop 產生緣由和代碼演示。
  • 第四章 瀏覽器 Event Loop:解惑工做困擾和擴展必備面試知識點。
  • 第五章 Node.js Event Loop:進一步探索瀏覽器和 Node.js 中 Event Loop 的不一樣。

OK,Let's go!面試

三 Event Loop

返回目錄算法

  • 問:什麼是 Event Loop,爲何須要 Event Loop?

答:

首先,咱們須要知道的是:JavaScript 是單線程的。

單線程意味着,全部任務都須要排隊,前一個任務結束,纔會執行後一個任務。

假設 jsliang 和 JavaScript 同樣一次只能作一件事,那麼大概就是以下圖所示。

而這種 主線程從 「任務隊列」 中讀取執行事件,不斷循環重複的過程,就被稱爲 事件循環(Event Loop)

而後,若是前一個任務耗時很長,後一個任務就不得不一直等着,那麼咱們確定要對這種狀況作一些特殊處理,畢竟不少時候咱們並非徹底但願它如此執行。

因此爲了協調事件(event),用戶交互(user interaction),腳本(script),渲染(rendering),網絡(networking)等,用戶代理(user agent)必須使用事件循環(event loops)。

這樣,在瞭解 瀏覽器 Event LoopNode.js Event Loop 的狀況下,咱們就能夠了解它的執行過程。

經過自身的瞭解,來處理一些較爲棘手的問題。

爲了加深小夥伴們的印象,能夠看下圖:

jsliang 平常中,強制被加上了 「被豆豆媽打」(廢話,豆豆那麼可愛,你怎麼能夠打豆豆)。

固然,這個被打的順序也不必定是在後面,可能打多兩次後,「睡覺」 完以後就是 「被豆豆媽打」 了。

經過這個解釋,小夥伴們應該知道爲啥有 瀏覽器 Event LoopNode.js Event Loop 了。

等等,你剛纔說到了 瀏覽器 Event LoopNode.js Event Loop,爲何都是關於 JavaScript 的,在這兩部分都不同呢?

  • 簡單來講:你的頁面放到了瀏覽器去展現,你的數據放到了後臺處理(將 Node.js 當作 PHP、Java 等後端語言),這二者能沒有區別麼?!

你說了跟沒說同樣,爲何會這樣你沒有解釋啊!

好的,說得再仔細點:

  • Node.js:Node.js 的 Event Loop 是基於 libuv。libuv 已經對 Event Loop 做出了實現。
  • 瀏覽器:瀏覽器的 Event Loop 是基於 HTML5 規範的。而 HTML5 規範中只是定義了瀏覽器中的 Event Loop 的模型,具體實現留給了瀏覽器廠商。

libuv 是一個多平臺支持庫,主要用於異步 I/O。它最初是爲 Node.js 開發的,如今 Luvit、Julia、pyuv 和其餘的框架也使用它。Github - libuv 倉庫

恍然大悟,的確是不同的啊!

因此,我們得將這兩個 Event Loop 區分開來,它們是不同的東東哈~

最後,我們解疑開頭的兩個問題,爲何會這樣子,有沒辦法解決?

  • 疑惑一:爲何這份代碼它不按照個人意思走?爲啥不是輸出 1 2 3
for (var i = 0; i < 3; i++) {
  setTimeout(() => {
    console.log(i);
  }, 1000);
}
// console:
// 3
// 3
// 3
複製代碼

這道題是面試常備題,它是個頗有意思的問題,不只可讓面試官跟你閒聊到 Event Loop,也能夠閒聊下 var let const

爲此,jsliang 特地錄製了一個 GIF,但願能幫助小夥伴進一步探索這個機制:

軟件是 VS Code,調試方式是 Node.js

請仔細觀看 GIF 圖:

  1. 在執行 for 遍歷的時候,它先執行了和 setTimeout 同級的 console,而後往下執行,到 setTimeout 的時候,跳過了(放到某個位置)setTimeout,依次打印了 0, 1, 2
  2. 步驟 1 跳過的三次 setTimeout 開始執行,可是這時候的 i 的值,通過前面的 i++ 後,變成了 3for 停止循環後,i 已是 3 了)。因此,再依次打印了 3 3 3

就是說,先走了正常的 for,而後碰到 setTimeout 時,將 setTimeout 依次放到了異次元,最後走完 for 後,再將異次元中的的 setTimeout 放出,依次將數字給輸出了。

這個執行機制,就是 Event Loop 的影響,恍然大悟有木有~

這個問題的精妙之處在於,它不只能夠問你關於 Event Loop 的部分,還能夠考察你對於 ES6 的 let 和 ES5 的 var 的區分,由於它有一個解決方式就是使用了 ES6 的 let

解決這個問題以前,不妨思考下下面的輸出:

for (var i = 0; i < 3; i++) {

}
for (let j = 0; j < 3; j++) {

}
console.log(i);
console.log(j);
複製代碼

若是小夥伴對 ES6 有些許瞭解,應該不難猜出:

3
ReferenceError: j is not defined
複製代碼

是否是有些想法,那麼我們再看下下面的解決方法,再進行總結:

for (let i = 0; i < 3; i++) {
  setTimeout(() => {
    console.log(i);
  }, 1000);
}
// console:
// 0
// 1
// 2
複製代碼

是的,將 var i 改爲了 let i 後,輸出的結果依次是 0 1 2 了。

爲何呢?簡單回覆就是:

letfor 中造成了獨特的做用域塊,當前的 i 只在本輪循環中有效,而後 setTimeout 會找到本輪最接近的 i,從而做出了正確的輸出。

而咱們經過 var 進行的定義,它會污染全局變量,因此在 for 外層,還能夠看到 i 的值。

固然,講到這裏,你可能仍是不太清楚更細節的區分,亦或者面試官進一步問你 var let const 的區分了,你要怎麼更好回答?

看看阮一峯大佬的 ES6 文檔吧:es6.ruanyifeng.com/#docs/let

這裏就不哆嗦了,有空我再將 ES6 這塊內容整理到個人文檔庫中,歡迎持續關注 jsliang 的文檔庫:github.com/LiangJunron…

  • 疑惑二:爲何這份代碼它也不按照個人意思走?爲啥不是輸出 梁峻榮
let name;

setTimeout(() => {
  name = 'jsliang';
  console.log(name);
}, 1000);

if (name) {
  name = '梁峻榮';
  console.log(name);
}
// console: 'jsliang'
複製代碼

當你瞭解產生疑惑一的緣由後,疑惑二也就不破而解了。

咱們但願的是 JavaScript 按照咱們須要的順序寫,結果它並無,就是由於受到了 Event Loop 的影響。

JavaScript 在碰到 setTimeout 的時候,會將它封印進異次元,只有等全部正常的語句(iffor……)執行完畢後,纔會將它從異次元解封,輸出最終結果。

咦,這就有意思了,瀏覽器的異次元和 Node.js 的異次元都是怎樣的呢?咱們一塊兒往下看。

四 瀏覽器 Event Loop

返回目錄

在講解瀏覽器的 Event Loop 前,咱們須要先了解一下 JavaScript 的運行機制:

  1. 全部同步任務都在主線程上執行,造成一個 「執行棧」(execution context stack)。
  2. 主線程以外,存在一個 「任務隊列」(task queue),在走主流程的時候,若是碰到異步任務,那麼就在 「任務隊列」 中放置這個異步任務。
  3. 一旦 「執行棧」 中全部同步任務執行完畢,系統就會讀取 「任務隊列」,看看裏面存在哪些事件。那些對應的異步任務,結束等待狀態,進入執行棧,開始執行。
  4. 主線程不斷重複上面三個步驟。

而 JavaScript 的異步任務,還細分兩種任務:

  • 宏任務(Macrotask)script(總體代碼)、setTimeoutsetIntervalXMLHttpRequest.prototype.onloadI/O、UI 渲染
  • 微任務(Microtask)PromiseMutationObserver

這麼講是不太容易理解的,我們上圖:

圖較大,若是是公衆號看的小夥伴,能夠點擊【閱讀原文】看全圖

好的,若是小夥伴們看不清楚,那麼我們仍是經過代碼來進行講解,畢竟以上屬於 jsliang 我的理解,是從 15 篇以上文章和本身觀察代碼運行總結出來的。

4.1 示例 1

返回目錄

那麼,上代碼~

示例 1

// 位置 1
setTimeout(function () {
  console.log('timeout1');
}, 1000);

// 位置 2
console.log('start');

// 位置 3
Promise.resolve().then(function () {
  // 位置 5
  console.log('promise1');
  // 位置 6
  Promise.resolve().then(function () {
    console.log('promise2');
  });
  // 位置 7
  setTimeout(function () {
    // 位置 8
    Promise.resolve().then(function () {
      console.log('promise3');
    });
    // 位置 9
    console.log('timeout2')
  }, 0);
});

// 位置 4
console.log('done');
複製代碼

提問:請指出上面代碼的輸出結果?

回答

這是經典的面試題型,因此我們看到不用慌,先拿咱們上面的點,區分下分宏任務和微任務:

  • 宏任務(Macrotask)script(總體代碼)、setTimeoutsetIntervalXMLHttpRequest.prototype.onloadI/O、UI 渲染
  • 微任務(Microtask)PromiseMutationObserver

OK,開始走流程:

若是你以爲文字很差理解,請往下翻,有 GIF 圖演示!!!

  1. 首先碰到的是 script(總體代碼),先看【位置 1】,屬於宏任務 setTimeout 下的,因此作個標記,待會回來執行。
  2. 接着碰到【位置 2】,這是 script(總體代碼)下的無阻礙代碼,直接執行便可。
  3. 再來碰到【位置 3】,它如今是 script(總體代碼)下的微任務,因此我們作個標記,走完文件全部代碼後,優先執行微任務,再執行宏任務。
  4. 最後碰到【位置 4】,它是 script(總體代碼)下的無阻礙代碼,直接執行便可。

這樣,第一波步驟,咱們輸出的是【位置 2】的 start 和【位置 4】的 done

咱們接着走:

  1. 上面咱們走完了第一遍代碼,而後如今這一步先走 script(總體代碼)下的微任務,即【位置 3】
    1. 先碰到【位置 5】,這是無阻礙代碼,直接執行。
    2. 再碰到【位置 6】,這是微任務,標記一下,等下執行完【位置 3】內全部代碼後,優先執行它。
    3. 最後碰到【位置 7】,這是宏任務,丟入任務隊列,看它和【位置 1】誰先走了。
  2. 走完一遍【位置 3】後,發現還有微任務【位置 6】,因此執行【位置 6】,進行打印輸出。

到這一步,咱們就走完了 script(總體代碼)及之下的全部微任務了。

這時候,咱們會說,【位置 1】和【位置 7】都被丟到任務隊列了,是否是【位置 1】先走呢?

答案爲:不是的。

一樣的 setTimeoutjsliang 在測試的時候,就發現它們的輸出結果在各個環境都有本身的流程,有時候先走【位置 7】,再走【位置 1】;而有時候先走【位置 1】,再走【位置 7】。

固然,若是你指定是在 Chrome 的控制檯輸出一下上面的代碼,那就是先【位置 7】,再【位置 1】~

  • point:不要主觀臆斷某個代碼會怎麼走,最好仍是直接實況運行走一波!
  1. 先走【位置 7】。碰到【位置 8】,將其添加到【位置 7】的微任務中,等【位置 7】全部代碼執行完畢回來優先走微任務;碰到【位置 9】,這是無阻礙代碼,直接輸出便可。
  2. 執行【位置 7】的微任務【位置 8】,輸出對應文本。
  3. 最後走【位置 1】,輸出對應文本。

因此答案是:

start
done
promise1
promise2
timeout2
promise3
timeout1
複製代碼

你猜對沒有?

沒有能夠看下 GIF 圖加深印象:

4.2 示例 2

返回目錄

在上面,jsliang 花費了許多口水,講了一些繁雜冗餘的步驟,因此下面這個示例,請小夥伴們先自行猜設,得出結論後再翻看答案和調試 GIF~

示例 2

console.log("script start");

setTimeout(function() {
  console.log("setTimeout---0");
}, 0);

setTimeout(function() {
  console.log("setTimeout---200");
  setTimeout(function() {
    console.log("inner-setTimeout---0");
  });
  Promise.resolve().then(function() {
    console.log("promise5");
  });
}, 200);

Promise.resolve()
  .then(function() {
    console.log("promise1");
  })
  .then(function() {
    console.log("promise2");
  });
Promise.resolve().then(function() {
  console.log("promise3");
});
console.log("script end");
複製代碼



  • 輸出結果
script start
script end
promise1
promise3
promise2
setTimeout---0
setTimeout---200
promise5
inner-setTimeout---0
複製代碼
  • GIF 演示

4.3 示例 3

返回目錄

最後再看一個示例:

示例 3

setTimeout(function() {
  console.log(4);
}, 0);

const promise = new Promise(function executor(resolve) {
  console.log(1);
  for (var i = 0; i < 10000; i++) {
    i == 9999 && resolve();
  }
  console.log(2);
}).then(function() {
  console.log(5);
});

console.log(3);
複製代碼



  • 輸出結果
1
2
3
5
4
複製代碼

若是不經常使用 Promise 的小夥伴,可能對此感到疑惑,爲啥不是:3 1 2 5 4

手動滑稽,別問,問就是進一步探索 Promise

固然,還沒將全部探索結果更新,若是有小夥伴催更會加快速度,歡迎留言或者私聊催更,哈哈~

4.4 小結

返回目錄

這樣,咱們就經過 3 個示例,大體瞭解了瀏覽器的 Event Loop。

固然,實際應用中的代碼,何止這麼簡單,甚至有時候,面試官給你的面試題,也會讓你瞠目結舌。

因此,這裏我們廢話兩點:

  1. 你能夠了解宏任務和微任務的大致執行,例如先走 if...else...,再走 Promise……可是,詳細到每一個 point 都記下來,這裏不推薦。大人,時代在進步,記住死的不如多在業務實踐中嘗試,取最新的知識。
  2. 瀏覽器的 Event Loop 和 Node.js 的 Event Loop 不一樣,萬一哪天 XX 小程序搞另類,有本身的 Event Loop,你要一一記住嗎?

碰到問題不要慌,程序員,折騰就對了~

五 Node.js Event Loop

返回目錄

那麼,下面我們吐槽下 Node.js 的 Event Loop。

說實話,看完 Node 官網和大佬們關於 Node.js 的 Event Loop 講解,讓我想起了 Vue、React、微信小程序 的【生命週期】,再聯想到咱們的人生彷彿就像被寫死的程序同樣週期性、事件性運行,很是可惡,哈哈~

上面咱們講解過:Node.js 的 Event Loop 是基於 libuv。libuv 已經對 Event Loop 做出了實現。

那麼其機制是怎樣子的呢?看圖:

┌───────────────────────────┐
┌─>│           timers          │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
│  │     pending callbacks     │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
│  │       idle, prepare       │
│  └─────────────┬─────────────┘      ┌───────────────┐
│  ┌─────────────┴─────────────┐      │   incoming:   │
│  │           poll            │<─────┤  connections, │
│  └─────────────┬─────────────┘      │   data, etc.  │
│  ┌─────────────┴─────────────┐      └───────────────┘
│  │           check           │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
└──┤      close callbacks      │
   └───────────────────────────┘
複製代碼

關於這 6 個階段,官網描述爲:

  • 定時器(timers):本階段執行已經被 setTimeout()setInterval() 的調度回調函數。
  • 待定回調(pending callbacks):執行延遲到下一個循環迭代的 I/O 回調。
  • idle, prepare:僅系統內部使用。
  • 輪詢(poll):檢索新的 I/O 事件;執行與 I/O 相關的回調(幾乎全部狀況下,除了關閉的回調函數,那些由計時器和 setImmediate() 調度的以外),其他狀況 Node 將在適當的時候在此阻塞。
  • 檢測(check)setImmediate() 回調函數在這裏執行。
  • 關閉的回調函數(close callbacks):一些關閉的回調函數,如:socket.on('close', ...)

固然,這裏 jsliang 並不想多此一舉,將官網或者其餘大佬的文章照搬過來講是本身的,推薦小夥伴們閱讀官網關於 Event Loop 的各個階段的描述,以期在工做中有所使用:

Node.js 在不停的探索中,也會有所更新,因此正應了 jsliang 在瀏覽器 Event Loop 中的小結所說:不要限定死本身的知識點,與時俱進纔是王道

Node.js v9.5.0 Event Loop

┌───────────────────────┐
┌─>│        timers         │
│  └──────────┬────────────┘
│  ┌──────────┴────────────┐
│  │     I/O callbacks     │
│  └──────────┬────────────┘
│  ┌──────────┴────────────┐
│  │     idle, prepare     │
│  └──────────┬────────────┘      ┌───────────────┐
│  ┌──────────┴────────────┐      │   incoming:   │
│  │         poll          │<─────┤  connections, │
│  └──────────┬────────────┘      │   data, etc.  │
│  ┌──────────┴────────────┐      └───────────────┘
│  │        check          │
│  └──────────┬────────────┘
│  ┌──────────┴────────────┐
└──┤    close callbacks    │
   └───────────────────────┘
複製代碼

可是,迫於生活所需,有些時候,前端面試官仍是會跟你扯 setTimeout & setImmediateprocess.nextTice()

5.1 setTimeout & setImmediate

返回目錄

  • setTimeout:衆所周知,這是一個定時器,指定 n 毫秒後執行定時器裏面的內容。
  • setImmediate:Node.js 發現使用 setTimeoutsetInterval 有些小弊端,因此設計了個 setImmediate,該方法被設計爲一旦在當前輪詢階段完成,就執行這個腳本。

固然,光說無益,看代碼:

index.js

setTimeout(() => {
  console.log('timeout');
}, 0);

setImmediate(() => {
  console.log('immediate');
});
複製代碼

猜想下在 VS Code 中執行 node index.js 命令會發生什麼?

結局 1

immediate
timeout
複製代碼

結局 2

timeout
immediate
複製代碼

事實上這兩個結局都是會存在的,看似 happy ending,可是有的小夥伴可能內心鬧翻天。

按照官網的解釋:

  • 執行計時器的順序將根據調用它們的上下文而異。
  • 若是兩則都從主模塊內調用,則計時器將受到進程性能的約束(這可能會受到計算機上其餘正在運行應用程序的影響)。
  • 若是你將這兩個函數放入一個 I/O 循環內調用,setImmediate 老是被有限調用。
const fs = require('fs');

fs.readFile(__filename, () => {
  setTimeout(() => {
    console.log('timeout');
  }, 0);
  setImmediate(() => {
    console.log('immediate');
  });
});
複製代碼

雖然官方解釋的很 巧妙,可是無論你懂不懂,反正我以爲有點扯淡。

最後再來句官方總結:

  • 使用 setImmediate() 相對於 setTimeout 的主要優點是:若是 setImmediate() 是在 I/O 週期內被調度的,那麼它將會在任何的定時器以前執行,跟這裏存在多少個定時器無關。

enm...後面若是我具體使用 Node.js 的時候,我再進一步觀察吧,至於如今,我仍是先了解下便可。

5.2 process.nextTick()

返回目錄

nextTick 比較特殊,它存有本身的隊列。

而且,它獨立於 Event Loop,不管 Event Loop 處於何種階段,都會在階段結束的時候清空 nextTick 隊列。

還有須要注意的是:process.nextTick() 優先於其餘的微任務(microtask)執行。

固然,若是你對此有所興趣,你能夠進一步探索源碼,或者觀察大佬們探索源碼:

沒有使用就沒有發言權,做爲一個 Node.js 菜雞,這裏就不妄加評論分析了。

5.3 示例 1

返回目錄

下面開始示例,咱們看下 Node.js 的 Event Loop 有何差別:

示例 1

setTimeout(() => {
  console.log("timer1");
  Promise.resolve().then(function() {
    console.log("promise1");
  });
});

setTimeout(() => {
  console.log("timer2");
  Promise.resolve().then(function() {
    console.log("promise2");
  });
});
複製代碼

若是你還記得上面講解的瀏覽器的 Event Loop,你可能會將答案直接寫成:

瀏覽器 Event Loop 輸出:

timer1
promise1
timer2
promise2
複製代碼

是的你是對的,那就是瀏覽器的 Event Loop,到了 Node.js 這塊,就有不一樣變化了:

Node.js Event Loop 輸出:

timer1
timer2
promise1
promise2
複製代碼

嘗試接受它!

而後大聲默唸:根據具體環境進行對應觀察和得出結論

5.4 示例 2

返回目錄

下面我們再看一個示例:

示例 2

setTimeout(function () {
   console.log(1);
});
console.log(2);
process.nextTick(() => {
   console.log(3);
});
new Promise(function (resolve, rejected) {
   console.log(4);
   resolve()
}).then(res=>{
   console.log(5);
})
setImmediate(function () {
   console.log(6)
})
console.log('end');
複製代碼

node index.js

2
4
end
3
5
1
6
複製代碼

這裏不打算解析,由於我怕初識 Event Loop 的小夥伴看完解釋後懵逼,而後搞混淆了。

實話:我也不敢解析,由於我就是 Node.js 菜雞

5.5 小結

返回目錄

終上所述,咱們進行小結:

Node 端事件循環中的異步隊列也是這兩種:Macrotask(宏任務)隊列和 Microtask(微任務)隊列。

  • 常見的 Macrotask:setTimeoutsetIntervalsetImmediatescript(總體代碼)、 I/O 操做等。
  • 常見的 Microtask:process.nextTicknew Promise().then(回調) 等。

OK,我們就探索了一遍 Node.js 的 Event Loop 啦,可是由於咱還成就不了 Node.js 工程師,因此咱就不對其進行詳細探索,以避免和瀏覽器的 Event Loop 混淆了。

感興趣的小夥伴能夠自行探索咯~

六 總結

返回目錄

若是你看到這裏,你已經近乎懵逼,那麼,仍是那個建議:

  • 無論 Event Loop 在瀏覽器亦或者 Node.js 表現機制,最好的操做仍是在對應環境中進行嘗試。

你不能徹底保證你的記憶力是 OK 的,因此你只須要知道有這個問題,而後在工做中實踐解決便可。

enm...因此你看完了一篇水文,惟一的做用是讓你面試的時候,能愉快地玩耍一些簡單題目~

哈哈,Good luck.

若是你以爲個人文章還不錯,想持續關注或者加我微信好友,歡迎前往 github.com/LiangJunron… 進行 star 或者加微信。

七 參考文獻

返回目錄

感謝如下大佬們的文章,讓我受益頗多。

並在他們創做的基礎上,基於本身的想法,進行了整合。

  1. 《Tasks, microtasks, queues and schedules》 - Jake
  2. 《完全搞懂瀏覽器 Event-loop》 - 劉小夕
  3. 《完全理解 JS Event Loop(瀏覽器環境)》 - 93
  4. 《完全弄懂瀏覽器端的 Event-Loop》 - 長可
  5. 《什麼是瀏覽器的事件循環(Event Loop)?》 - 魚子醬
  6. 《理解event loop(瀏覽器環境與nodejs環境)》 - sugerpocket
  7. 《從 event loop 規範探究 JavaScript 異步及瀏覽器更新渲染時機》 - 楊敬卓
  8. 《跟着 Event loop 規範理解瀏覽器中的異步機制》 - fi3ework
  9. 《不要混淆 nodejs 和瀏覽器中的 event loop》 - youth7
  10. 《瀏覽器的 event loop 和 node 的 event loop》 - 金大光
  11. 《瀏覽器與 Node 的事件循環(Event Loop)有何區別?》 - 浪裏行舟
  12. 《瀏覽器和 Node 不一樣的事件循環(Event Loop)》 - toBeTheLight
  13. 《let 和 const 命令》 - 阮一峯
  14. 《Node.js Event Loop》 - Node.js 官網

不折騰的前端,和鹹魚有什麼區別!

jsliang 會天天更新一道 LeetCode 題解,從而幫助小夥伴們夯實原生 JS 基礎,瞭解與學習算法與數據結構。

浪子神劍 會天天更新面試題,以面試題爲驅動來帶動你們學習,堅持天天學習與思考,天天進步一點!

掃描上方二維碼,關注 jsliang 的公衆號(左)和 浪子神劍 的公衆號(右),讓咱們一塊兒折騰!

知識共享許可協議
jsliang 的文檔庫梁峻榮 採用 知識共享 署名-非商業性使用-相同方式共享 4.0 國際 許可協議進行許可。
基於github.com/LiangJunron…上的做品創做。
本許可協議受權以外的使用權限能夠從 creativecommons.org/licenses/by… 處得到。

相關文章
相關標籤/搜索