從一個實例中解釋分析javascript 中的預編譯

引言

在咱們寫了不少關於業務邏輯的代碼後、過程當中會遇到不少關於變量定義、變量提高、做用域的問題,理解完預編譯就清晰不少javascript

關於javascript運行的三個階段

1.語法分析

引擎檢查你的代碼有沒有什麼低級的語法錯誤java

2.預編譯

預編譯簡單理解就是在內存中開闢一些空間,存放一些變量與函數面試

3.解釋執行

解釋執行顧名思義即是執行代碼了bash

關於預編譯發生的時機

發生在script內代碼塊執行前、也能夠說預編譯發生在函數執行的前一刻函數

從這個例子解釋疑惑

對於這樣一段代碼,常常在不少面試中會看到測試

let a = 0
function test(a,b){
    console.log(a)
    console.log(b)
    a = 1
    console.log(a)
    console.log(c)
    function c(){}
    function a(){}
    console.log(a)
}

test(1)
複製代碼

請問這段代碼的輸出是? 對於這樣的函數預編譯,咱們能夠記住預編譯的4個步驟ui

  • 建立AO對象
  • 找形參和變量聲明,將形參和變量名做爲AO對象的屬性名,值爲undefined
  • 將實參和形參統一
  • 函數的提高,在函數塊內找函數聲明,並修改對應屬性名的值,在下文解釋執行的階段改function將不會改變對象中屬性名的值

聽起來有點生澀難懂,可是咱們一行一行跟着這四個步驟一塊兒作的時候就明朗了spa

開始解題code

  • 建立AO對象,也稱活動對象,全程能夠理解爲active object,就是創建了一個空對象
AO{
    
}
複製代碼
  • 找形參和變量聲明,在test這個函數中形參有a,b,咱們把它寫到這個對象中,並把他們的值設置爲undefined
AO{
    a : undefined,
    b : undefined
}
複製代碼
  • 將實參和形參統一,第三步咱們須要去找到函數的參數,而且去改寫已經存在的屬性名的值,這個test函數的參數只傳了一個a:1,因此咱們改寫一下這個AO對象
AO{
    a : 1,
    b : undefined
}
複製代碼
  • 第四步也是我我的認爲最難理解的一個步驟,找到改函數體內的函數聲明
知足 function a(){}這樣的叫函數聲明 而相似於let a = function(){} 這樣的並非函數聲明
複製代碼

咱們找到了a、c函數聲明,咱們須要去改寫AO對象中對應的屬性名,因爲c這個屬性名並不存在,咱們要建立並用函數賦值,所以咱們獲得了這樣一個對象對象

AO{
    a : function(){},
    b : undefined,
    c : function(){}
}
複製代碼

而且在函數的解釋執行階段並不會對對應AO對象的屬性名進行值的改寫

至此,預編譯階段結束,進行到函數的解釋執行階段

let a = 0

/**
 * 測試函數
 * @param {*} a 
 * @param {*} b 
 * 
 * 
 * 
 * 咱們在預編譯結束的時候獲得這樣一個對象
 * {
 *  a:function(){},
 *  b:undefined,
 *  c:function(){}
 * }
 */
function test(a,b){
    console.log(a)
    console.log(b)
    a = 1
    console.log(a)
    console.log(c)
    function c(){}
    function a(){}
    console.log(a)
}

test(1)
複製代碼

下面咱們會逐字逐句解釋打印的值

  • 從第一行開始 第一個console.log(a) 得到的值應該是function(){}
  • console.log(b) 打印的應該是AO對象中b的值 爲undefined
  • a = 1 這一行會改寫AO對象的a的值
{
    a : 1,
    b : undefined,
    c : function(){}
}
複製代碼
  • 因此 a = 1 後面一行的console.log(a) 應該打印出1
  • console.log(c) 打印AO對象中的c的值 爲 function(){}
  • 我在第四個步驟中談到了在解釋執行階段的函數聲明並不會去修改AO對象中的屬性名的值了 因此function a(){} function c(){}不會修改AO對象了
  • 最後一個console.log(a) 打印出的值應該是 1

至此、這個實例解釋完畢

若是從全局出發,則是建立一個GO對象,顧名思義Global Object,其四個步驟和函數內的預編譯四個步驟同樣

相關文章
相關標籤/搜索