JavaScript的預編譯過程分析

張優秀發表於2019-02-16

一、JavaScript概念

JavaScript ( JS ) 是一個單執行緒、解釋型的程式語言。

二、JavaScript語言特點

2.1 單執行緒

JavaScript語言的一大特點就是單執行緒,也就是說,同一個時間只能做一件事。

2.2 解釋型語言

自上而下,解釋一行,執行一行;不會通篇編譯為一個檔案再執行。

三、 JavaScript執行過程

3.1 語法分析

顧名思義 就是檢查一遍js程式碼內有沒有出現語法錯誤(比如少些個分號,多寫個括號等);語法分析期間不會執行程式碼

3.2 預編譯

預編譯發生在函式執行的前一刻
全域性下:
全域性的變數宣告和函式宣告則會存放在全域性物件內(Global Object 簡稱GO,它是window的一部分,你可以直接把他理解成window物件)中
函式體內:
預編譯會提前把函式裡的變數宣告和函式宣告依據規則存放在該活動物件內(Activation Object,簡稱AO),

預編譯簡單理解就是在記憶體中開闢一些空間,存放一些變數與函式 。

預編譯大致可分為4步:

  1. 建立AO(GO)物件
  2. 找形參和變數宣告,將形參和變數名作為AO(GO)屬性名,值為undefined
  3. 將實參值和形參統一
  4. 在函式體裡面找函式宣告,值賦予函式體。

所以如果遇到下面這種情況,當函式宣告和變數宣告名稱相同時:

console.log(a); 
var a= 1;
function a(){};

編譯後的程式碼其實是:

var a;
function a(){};
console.log(a);
a= 1;

所以最後輸出的是:

function a() {}

預編譯小節

預編譯兩個小規則

  1. 函式宣告整體提升—(具體點說,無論函式呼叫和宣告的位置是前是後,系統總會把函式宣告移到呼叫前面)
  2. 變數 宣告提升—(具體點說,無論變數呼叫和宣告的位置是前是後,系統總會把宣告移到呼叫前,注意僅僅只是宣告,所以值是undefined),只有在解釋執行階段才會進行變數初始化,匿名函式不參與預編譯。

預編譯前奏

  1. imply global 即任何變數,如果未經宣告就賦值,則此變數就位全域性變數所有(全域性域就是window) 。
  2. 一切宣告的全域性變數,全是window的屬性。
<script>
  var a=2; 
  console.log(window.a);//2
</script>

3.3 解釋執行

預編譯完畢之後,JavaScript 指令碼開始執行,執行順序按照從上到下的順序執行。

總結

JavaScript執行順序

  1. 語法分析
  2. 預編譯
    2.1. 建立AO(GO)物件
    2.2. 找形參和變數宣告,將形參和變數名作為AO(GO)屬性名,值為undefined
    2.3. 將實參值和形參統一
    2.4. 在函式體裡面找函式宣告,值賦予函式體。
  3. 解釋執行

練習:

function a(a){
    console.log(a);
    a= 2;
    console.log(b);
    var b= 3;
    console.log(a);
}
a(1);
console.log(a);

你可以先試想一下結果,然後複製程式碼到控制檯去驗證你的答案是否正確。

相關文章