前端 知識點 作用域和作用域鏈

作用域

作用域就是變量和函數的可訪問範圍,控制着變量和函數的可見性與生命週期,JavaScript中只有全局作用域與局部作用域

如何判斷是全局還是局部作用域?

全局:

  • 最外層函數和在最外層函數外面定義的變量擁有全局作用域
  • 所有末定義直接賦值的變量自動聲明爲擁有全局作用域
  • 所有window對象的屬性擁有全局作用域

局部:

  • 函數內部用var聲明的變量
var a=3; //全局變量
            function fn(b){ //局部變量
                c=2; //全局變量
                var d=5; //局部變量
                function subFn(){
                    var e=d; //父函數的局部變量對子函數可見
                    for(var i=0;i<3;i++){
                        console.write(i);
                    }
                    alert(i);//3, 在for循環內聲明,循環外function內仍然可見,沒有塊作用域
                }
            }
            alert(c); //在function內聲明但不帶var修飾,仍然是全局變量

作用域與執行上下文是完全不同的兩個概念。

JavaScript代碼的整個執行過程,分爲兩個階段,代碼編譯階段與代碼執行階段。編譯階段由編譯器完成,將代碼翻譯成可執行代碼,這個階段作用域規則會確定。執行階段由引擎完成,主要任務是執行可執行代碼,執行上下文在這個階段創建。

代碼的整個執行過程

作用域鏈

分析執行上下文的生命週期

這裏寫圖片描述

我們知道函數在調用激活時,會開始創建對應的執行上下文,在執行上下文生成的過程中,變量對象,作用域鏈,以及this的值會分別被確定。

作用域鏈,是由當前環境與上層環境的一系列變量對象組成,它保證了當前執行環境對符合訪問權限的變量和函數的有序訪問。

爲了幫助大家理解作用域鏈,我我們先結合一個例子來說明。

var a = 20;

function test() {
    var b = a + 10;

    function innerTest() {
        var c = 10;
        return b + c;
    }

    return innerTest();
}

test();

在上面的例子中,全局,函數test,函數innerTest的執行上下文先後創建。我們設定他們的變量對象分別爲VO(global),VO(test), VO(innerTest)。而innerTest的作用域鏈,則同時包含了這三個變量對象,所以innerTest的執行上下文可如下表示。

innerTestEC = {
    VO: {...},  // 變量對象
    scopeChain: [VO(innerTest), VO(test), VO(global)], // 作用域鏈
}

我們可以直接用一個數組來表示作用域鏈,數組的第一項scopeChain[0]爲作用域鏈的最前端,而數組的最後一項,爲作用域鏈的最末端,所有的最末端都爲全局變量對象。

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