深入理解JavaScript執行(單執行緒的JS)

前端猿Ry發表於2018-02-08

一、介紹

隨著js不斷深入,你可能會慢慢的好奇,用了這麼久的js,卻不知道這js在瀏覽器怎麼被執行的,很尷尬,哈哈。所以,我查閱很多資料來總結JS的執行過程,也分享出來,和大家一起學習。

本篇主要講單執行緒的JS
涉及的名詞:JS引擎,單執行緒,執行棧,執行上下文(execution context)

二、JS引擎

JS引擎是瀏覽器的重要組成部分,主要用於讀取並執行js。就是這傢伙執行js的,但它不止於執行js。

各大瀏覽器的JS引擎:

瀏覽器 Js引擎
Chrome V8
Firefox SpiderMonkey
IE Chakra(查克拉)
Safari Nitro/JavaScript Core
Opera Carakan

雖然每個瀏覽器的JS引擎都不同,但他們執行js機制大致相同。

三、JS執行是單執行緒

單執行緒是指Js引擎執行Js時只分了一個執行緒給他執行,也就是執行js時是單執行緒的。

先通俗的瞭解執行緒

  • 有人可能會疑惑,執行緒是什麼?

我直接舉個直觀點例子吧,你開啟一個瀏覽器(應用程式),那瀏覽器就是一個程式。開啟瀏覽器後要做很多事情(各種分工):傳送請求,接受請求,渲染頁面,執行js等等這些就是一個個執行緒。

我這裡只是簡單的說一下,具體的大家可以找計算機作業系統資料深入學習。

Js為什麼是單執行緒

  • 有可能有疑惑,為什麼js執行要單執行緒,如果多執行緒不是可以執行得快一點嗎?

這個要回到Js歷史了,布蘭登·艾奇(Brendan Eich)老哥用10天創造js。當時js用來幹嘛,簡單的瀏覽器互動,驗證,操作一下dom是吧。那把它設計成那麼複雜幹什麼,而且如果多執行緒的話,操作dom會出現麻煩的事情,假設一個執行緒讀取DOM節點資料的同時,另一個執行緒把那個DOM節點刪了,呵呵。所以js一個執行緒就夠了,也就是一步一步順序執行下來。

證明一下js執行是單執行緒

單執行緒只能一個個排著隊執行,所以執行以下程式碼會導致阻塞(有個while死迴圈),不會彈出hello

while(1){}
alert('hello');
複製程式碼

四、執行棧

為了實現js執行時的單執行緒,js引擎維護著一個執行棧。(先進後出)

來個例子:執行這段程式碼時執行棧是怎麼做的。

//執行程式碼
sayHello();
function sayHello(){
    var message = getMessage();
    console.log(message);
}
function getMessage(){
    return 'hello';
}

複製程式碼

執行棧程式碼模擬

//執行棧
var exeStack = [];
//先壓如全域性執行環境
exeStack.push('globalContext');
//遇到執行sayHello函式,ok,壓進去
exeStack.push('sayHello');
//執行sayHello函式發現,還有個getMessage函式,ok,壓進棧
exeStack.push('getMessage');
//執行完了getMessage函式,彈棧
exeStack.pop();
//繼續執行sayHello函式,又發現有console.log這個傢伙,ok,你進棧
exeStack.push('console.log');
//執行了console後,輸出hello,console 彈棧
exeStack.pop();
//這時sayHello執行完,彈棧
exeStack.pop();
//最後整個程式碼執行完,全域性環境彈棧
exeStack.pop();
複製程式碼

執行棧圖示:

深入理解JavaScript執行(單執行緒的JS)

這裡主要是js在執行時的一個總體過程,但是你們可能會疑惑,壓進棧裡面的一塊塊(抽象)東西到底包含的是什麼?
我可以告訴你們是,執行上下文,global是指全域性的的執行上下文,其他的是函式執行上下文,那到底這些上下文包含什麼,我會在下一篇寫。

五、小結

這篇主要是將js單執行緒是什麼,並且怎麼實現單執行緒的。有個總體js執行過程的印象,接下來會講解更多裡面的東西。就像是挖掘機一樣,深挖下去。

如果你覺得困難,那也許就是在進步

相關文章