首先來看一段代碼javascript
function fn(){ console.log('1') setTimeout(() => { console.log('2') }, 1000) var aa = 0 for (let i = 0; i < 9999999999; i++) { aa = i } if (aa = 9999999998) { console.log('3') } } fn()
運行結果是先輸出1,而後大概好幾秒(大於一秒)
之後依次輸出3,2。java
setTimeout(() => { console.log('2') }, 1000)
但是上邊這裏明明寫了定時器一秒後
輸出字符串2啊,爲何過了很久才輸出呢?這裏就會引起思考,js究竟是怎麼執行的git
先來一張經典圖github
咱們都知道JS是單線程的,因此在它的stack(執行棧)裏面任務是排隊執行的,這裏咱們在回頭看開始的代碼瀏覽器
function fn(){ console.log('1') setTimeout(() => { console.log('2') }, 1000) var aa = 0 for (let i = 0; i < 9999999999; i++) { aa = i } if (aa = 9999999998) { console.log('3') } } fn()
當調用fn()的時候,就會把fn這個函數放到stack中去。執行步驟分如下幾步多線程
第一步:執行console.log('1')第二步:執行到setTimeout 的時候,由於咱們都知道setTimeout是異步操做,這裏不可能說我js停下來等你1秒,這樣頁面就卡死在那裏了。異步
這裏在回過頭來看上面那Event-loop圖函數
注:js是單線程,但js是運行在瀏覽器中的,瀏覽器是多線程的,這一點要搞清楚
當咱們運行到setTimeout這裏時,爲了避免阻塞頁面,瀏覽器會在開一個線程來處理異步的操做,也就是上圖紅框框部分。而後js會略過setTimeout,繼續執行下面for循環的代碼。
當一秒鐘以後setTimeout執行完畢,就會將結果放如到callback queue(回調隊列中等待調用),等待stack中的任務執行完畢後來調用它,因此一開始fn()函數的執行結果是1,3,2,、不是1,2,3.就是由於異步的操做被放在了callback queue中,等待stack中的執行完纔會去找它。oop
如今咱們搞明白了爲何結果是1,3,2 而不是1,2,3,以後還有一個問題就是爲何setTimeout明明寫的是1秒以後在控制檯打印出'2'來,爲何實際體驗中要好幾秒以後呢。緣由就在如下這部分代碼中post
for (let i = 0; i < 9999999999; i++) { aa = i } if (aa = 9999999998) { console.log('3') }
緣由就是這部分for循環的代碼執行過程超過了1秒。而這個for循環是放在stack裏面的。它執行不完就不會去callback queue裏面找東西,因此咱們看到的最終結果就是
先打印'1'出來 而後等幾秒後(這個隨電腦配置不一樣,時間長短不同),在打印出'2' 最後纔會打印出'3'