想必面試題刷的多的同窗對下面這道題目不陌生,可以當即回答出輸出10個10,但是你真的懂爲何嗎?爲何是輸出10?爲何是輸出10個10?這兩個問題在我腦邊縈繞。嗯,我得說服本身。html
for (var i = 0; i < 10; i++) { setTimeout(() => { console.log(i) }, 0) }
JavaScript 是單線程。(ok,我又問本身它爲何是單線程 ==》做爲瀏覽器語言,JS的用途是與用戶交互以及操做DOM,若是是多線程會引起不少問題,瀏覽器沒法判斷以哪一個線程爲標準,所以它只能是單線程)
任務分爲「同步任務」與「異步任務」。同步任務都好理解,一個執行完執行下一個。異步任務稍許複雜。
異步任務運行機制:java
其實屢清楚很好理解,以上運行機制又稱爲 Event Loop
(事件循環)
咱們回到這道面試題, 一塊兒來理解下:git
for 循環是同步任務,setTimeout 是異步任務 首先 for 循環在主線程上執行,setTimeout 進入任務隊列 同步任務執行完,i = 10,此時 setTimeout 被喚醒進入執行棧執行 所以輸出的值爲10 但是爲何會輸出10個10呢?到如今我仍是沒有徹底說服本身。
咱們對代碼稍做修改,github
for (var i = 0; i < 10; i++) { console.log(i) var p = setTimeout(() => { console.log(i) }, 0) console.log(p) }
輸出結果面試
0 Timeout {_called: false, _idleTimeout: 1, _idlePrev: TimersList, _idleNext: TimersList, _idleStart: 1893, …} 1 Timeout {_called: false, _idleTimeout: 1, _idlePrev: TimersList, _idleNext: Timeout, _idleStart: 3739, …} 2 Timeout {_called: false, _idleTimeout: 1, _idlePrev: TimersList, _idleNext: Timeout, _idleStart: 4924, …} ...... 9 Timeout {_called: false, _idleTimeout: 1, _idlePrev: TimersList, _idleNext: Timeout, _idleStart: 11733, …} 10 10 ... 10
看到這個結果你們是否有些清楚了呢,咱們從新梳理下原先的面試題瀏覽器
首先 for 循環在主線程上執行,setTimeout 內部的回調函數進入任務隊列 for 循環裏,i 每次執行一次,異步隊列裏放置一個 setTimeout 回調 同步任務執行完,i = 10, 此時異步隊列裏放置了10個回調事件 setTimeout 被喚醒進入執行棧執行 所以輸出了10個10
固然了, Event Loop
的知識不止這點,涉及到的東西也不少。本文只是我對這道面試題的一點思考,有誤的地方望批評指正。多線程
如下幾篇是我收藏的好文,供你們學習參考~
JavaScript 運行機制詳解:再談Event Loop
這一次,完全弄懂 JavaScript 執行機制
從event loop規範探究javaScript異步及瀏覽器更新渲染時機異步