關於變量提升和函數提升的理解

變量提升:變量的聲明寫在可以在使用變量之後;
函數提升:函數可以先調用,後聲明;

上面先解釋了下我理解的這兩個概念的定義。要真正理解它們,最好從變量對象的角度出發。引出變量對象的概念,要先理解執行上下文,也就是當控制器執行到可執行代碼的時候,就會生成一個執行上下文,也就是代碼的執行環境,會產生一個作用域。這個執行上下文的生命週期有兩個階段:創建階段代碼執行階段

創建階段就會創建變量對象,創建的過程分三步:

1.建立arguments對象。檢查當前上下文中的參數,建立該對象下的屬性與屬性值
2.先檢查有沒有函數聲明(利用function關鍵字聲明的函數,在變量對象中用函數名作爲屬性名,屬性值是函數內存地址
的引用。如果函數名的引用已經存在,那麼會被新的引用覆蓋)
3.再檢查變量聲明,每找到一個變量聲明,就在變量對象裏用變量名作爲屬性名,屬性值是undefined。如果變量名已經存在,直接跳過,目的是防止把同名的函數被修改成undefined

執行階段會將變量對象轉換爲活動對象:

創建完成之後,就會開始執行代碼,這個時候,會完成變量賦值,函數引用,以及執行其他代碼。
(在變量對象創建過程中,其中的屬性不可訪問。只有在執行階段轉爲活動對象後,纔可以訪問其中的內容)

先來一個簡單的例子:

function foo(){
    a = 2;
    function a(){
        console.log("函數")
    }
    console.log(a); //2
    var a;
};
foo();

這個例子中,當控制器遇到這段代碼時候,會形成一個執行上下文。隨後進入到執行上下文的第一個生命週期:創建階段,此時,執行創建變量對象的三個步驟。

  • 由於沒有參數。直接進入第二步。
  • 首先檢查上下文中有沒有function關鍵字聲明的函數,以a爲屬性名,函數的引用爲屬性值,添加到變量對象中。
  • 再檢查函數聲明,發現了變量名a,但是,以a爲屬性名的屬性值已經存在,所以跳過。

接下來進入第二個生命週期:代碼執行

a被賦值爲2,函數a未被調用。打印a等於2

函數提升也是一個道理,由於變量對象創建過程中會先檢查function關鍵字聲明的函數,以該函數的函數名爲屬性,值爲函數地址的引用,添加進變量對象中。

參考:前端基礎進階(三):變量對象詳解 關於JavaScript變量提升的理解

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章