JS是單線程的,或者說只有一個主線程,也就是它一次只能執行一段代碼。JS中實際上是沒有線程概念的,所謂的單線程也只是相對於多線程而言。JS的設計初衷就沒有考慮這些,針對JS這種不具有並行任務處理的特性,咱們稱之爲「單線程」。javascript
雖然JS運行在瀏覽器中是單線程的,可是瀏覽器是事件驅動的(Event driven),瀏覽器中不少行爲是異步(Asynchronized)的,會建立事件並放入執行隊列中。瀏覽器中不少異步行爲都是由瀏覽器新開一個線程去完成,一個瀏覽器至少實現三個常駐線程:java
JavaScript引擎是一個專門處理JavaScript腳本的虛擬機,通常會附帶在網頁瀏覽器之中,好比最出名的就是Chrome瀏覽器的V8引擎,以下圖所示,JS引擎主要有兩個組件構成:ajax
每個函數執行的時候,都會生成新的execution context(執行上下文),執行上下文會包含一些當前函數的參數、局部變量之類的信息,它會被推入棧中, running execution context(正在執行的上下文)始終處於棧的頂部。當函數執行完後,它的執行上下文會從棧彈出。 數據庫
舉個簡單的例子:function bar() {
console.log('bar');
}
function foo() {
console.log('foo');
bar();
}
foo();
複製代碼
執行過程當中棧的變化: promise
Wikipedia這樣定義:瀏覽器
"Event Loop是一個程序結構,用於等待和發送消息和事件。(a programming construct that waits for and dispatches events or messages in a program.)"bash
簡單說,就是在程序中設置兩個線程:一個負責程序自己的運行,稱爲"主線程";另外一個負責主線程與其餘進程(主要是各類I/O操做)的通訊,被稱爲"Event Loop線程"(能夠譯爲"消息線程")。 多線程
事件循環能夠簡單描述爲:併發
接下來看一個異步函數執行的例子:異步
var start=new Date();
setTimeout(function cb(){
console.log("時間間隔:",new Date()-start+'ms');
},500);
while(new Date()-start<1000){};
複製代碼
其實咱們上面所說的都是宏任務(Macrotasks),可是js中還有一種隊列微任務(Microtasks)。
macro-task(Task):一個event loop有一個或者多個task隊列。task任務源很是寬泛,好比ajax的onload,click事件,基本上咱們常常綁定的各類事件都是task任務源,還有數據庫操做(IndexedDB ),須要注意的是setTimeout、setInterval、setImmediate也是task任務源。總結來講task任務源:
micro-task(Job):microtask 隊列和task 隊列有些類似,都是先進先出的隊列,由指定的任務源去提供任務,不一樣的是一個 event loop裏只有一個microtask 隊列。另外microtask執行時機和Macrotasks也有所差別
那麼Macrotasks和Microtasks有什麼別區別呢
舉個簡單的例子,假設一個script標籤的代碼以下:
Promise.resolve().then(function promise1 () {
console.log('promise1');
})
setTimeout(function setTimeout1 (){
console.log('setTimeout1')
Promise.resolve().then(function promise2 () {
console.log('promise2');
})
}, 0)
setTimeout(function setTimeout2 (){
console.log('setTimeout2')
}, 0)
複製代碼
運行過程:
script裏的代碼被列爲一個task,放入task隊列。
*【task隊列:setTimeout1 setTimeout2;microtask隊列:】 4. 從task隊列中取出setTimeout1,推入棧中執行,將promise2列爲microtask。
綜上所說,每次event loop循環執行棧完成後,會繼續執行完相應的microtask任務
這是event loop中很重要部分,在第7步會進行Update the rendering(更新渲染),規範容許瀏覽器本身選擇是否更新視圖。也就是說可能不是每輪事件循環都去更新視圖,只在有必要的時候才更新視圖。