讀過本文章後,您能知道:javascript
首先經過一段代碼來驗證你是否瞭解代碼輸出順序,若是你不知道輸出順序,那麼本文能夠幫助你瞭解:html
console.log(1) setTimeout(function () { new Promise(function (resolve) { console.log(2) resolve() }) .then(() => { console.log(3) }) }) setTimeout(function () { console.log(4) }) console.log(5)
JavaScript語言的執行是單線程(single thread)的。java
所謂的單線程,就是指一次只執行一個任務,若是有多個任務,就必須排隊,前面一個任務完成,才能執行後面任務。node
這種模式的好處是實現起來比較簡單,執行環境相對單純;壞處是隻要有一個任務耗時很長,後面的任務都必須排隊等待,會拖延整個程序的執行。常見的瀏覽器無響應(假死),每每就是由於某一段JavaScript代碼長時間運行(好比死循環),致使整個頁面卡在這個地方,其餘任務沒法執行。web
爲了解決這個問題,JavaScript語言將任務的執行模式分紅兩種:同步(Synchronous)和異步(Asynchronous)。面試
同步任務:在主線程上排隊執行的任務,只有前一個任務執行完畢,才能執行後一個任務。ajax
異步任務:不進入主線程、而進入"任務隊列"(task queue)的任務,只有"任務隊列"通知主線程,某個異步任務能夠執行了,該任務纔會進入主線程執行。chrome
JavaScript執行機制:segmentfault
一、全部同步任務都在主線程上執行,造成一個執行棧(execution context stack)。
二、主線程以外,還存在一個"任務隊列"(task queue)。只要異步任務有了運行結果,就在"任務隊列"之中放置一個事件。
三、一旦"執行棧"中的全部同步任務執行完畢,系統就會讀取"任務隊列",若是有有執行任務,則進入執行棧,開始執行。
四、主線程不斷重複上面的三步,此過程也就是常說的Event Loop(事件循環)。
當咱們調用一個方法的時候,js會生成一個與這個方法相對應的執行環境,也叫執行上下文,這個執行環境存在着這個方法的私有做用域、參數、this對象等等。由於js是單線程的,同一時間只能執行一個方法,因此當一系列的方法被依次調用的時候,js會先解析這些方法,把其中的同步任務按照執行順序排隊到一個地方,這個地方叫作執行棧。api
JavaScript是單線程的,那麼這個單線程就成爲主線程。而事件循環在主線程執行完執行棧代碼後,才執行的。因此主線程代碼執行時間過長,會阻塞事件循環的執行。只有當執行棧爲空的時候(同步代碼執行完畢),纔會執行事件循環來觀察有哪些事件回調須要執行,當事件循環檢測到任務隊列有事件就讀取出回調放到執行棧由主線程執行。
任務隊列也有時稱叫消息隊列、回調隊列。
異步操做會將相關回調添加到任務隊列中。而不一樣的異步操做添加到任務隊列的時機也不一樣,如onclick, setTimeout,ajax處理的方式都不一樣,這些異步操做是由瀏覽器內核的webcore來執行的,webcore包含下圖中的3種 webAPI,分別是DOM Binding、network、timer模塊。
如上圖所示,JavaScript總體執行過程:
也能夠參考以下連接:https://html.spec.whatwg.org/...
出現Promise後,JavaScript對於任務的定義除了廣義的同步任務和異步任務,又對任務作了更精細的定義,macrotask(宏任務)和 microtask(微任務):
注意:宏任務、微任務中出現的nodejs中的方法是nodejs專有的,瀏覽器的JavaScript環境暫時沒有支持。
有了宏任務和微任務後,JavaScript事件循環對此處理方法以下形式:
注意::此處把執行同步代碼算成第一個宏任務了。
以下代碼:
console.log('1'); setTimeout(function() { console.log('2'); new Promise(function(resolve) { console.log('3'); resolve(); }).then(function() { console.log('4') }) }) console.log('5'); setTimeout(function() { console.log('6'); new Promise(function(resolve) { console.log('7'); resolve(); }).then(function() { console.log('8') }) }) console.log('9');
上面代碼執行過程:
第一輪事件循環
第二輪事件循環
注意:瀏覽器環境JavaScript的執行機制和node中JavaScript的執行機制是不一樣的。