JS(九)作用域、作用域鏈精解

寫在最前面

作用域精解

  • [[scope]] : 每個JavaScript函數都是一個對象。對象中有些屬性我們可以訪問,但有些不可以,這些屬性僅提供JavaScript引擎存取,[[scope]]就是其中一個。
  • [[scope]]指的就是我們所說的作用域,其中存儲了運行期上下文的集合
  • 作用域鏈 : [[scope]]中存儲的執行期上下文對象的集合,這個集合呈鏈式鏈接,我們把這種鏈式鏈接叫做作用域鏈
  • 運行期上下文 : 當函數執行時,會創建一個稱爲執行期上下文的內部對象。一個執行期上下文定義了一個函數執行時的環境,函數每次執行時對應的執行上下文都是獨一無二的,所以多次調用一個函數會導致創建多個執行期上下文,當函數執行完畢,它所產生的執行上下文被銷燬
  • 查找變量 : 從作用域鏈的頂端依次向下查找
function a() {
    function b(){
        var b = 234;
    }

    var a = 123;

    b();
}

var glob = 100;
a();

首先我們來看上面的函數,這個是個整體的函數,a在這個全局的作用域裏面,然後下面有glob這個變量,然後有這個a執行;

第一步 : 首先系統看到的肯定是這個a定義,a定義的話有這個[[scope]]。

a
[[scope]]

scope指向scope chain

scope chain
0 這個位置的0指向GO
Global Object 0指向的是這個表
this window
window (object)
document (object)
a (function)
glob 100

[[scope]]裏面有這個全局的執行期上下文,然後a被執行了,a被執行,a產生的這個AO,把自己的AO存到作用域鏈的最頂端,形成一個新的作用域鏈,現在的a的[[scope]]和剛纔的那個[[scope]]不一樣了

a
[[scope]]

scope指向scope chain

scope chain
0 這個位置的0指向AO
1 這個位置的0指向GO
Activation Object 0指向的是這個表
this window
arguents []
a 123
b (function)
Global Object 1指向的是這個表
this window
window (object)
document (object)
a (function)
glob 100

它的不一樣只是裏面存的值不一樣了[[scope]]還是那個[[scope]],這個時候我們不看下面,這個時候假如我們訪問一個變量的話,我們訪問的是a的[[scope]],是從a的[[scope]]裏面拿東西,a的scope是一個倉庫,這個庫裏面存了個作用域鏈,裏面掛了各種變量,我去裏面拿東西的時候,就置頂向下去找。

然後a的執行,產生了b被定義,a執行了b才能被定義,b被定義的時候有個天生的[[scope]],[[scope]]裏面存了一個它所應該有的作用域鏈,但是它有的作用域鏈和a的不一樣,a被定義的時候,是在全局裏面,所能返訪問的屬性也只有它自己的AO還有全局的GO,但是b是在a函數裏面定義的,所以b的[[scope]]不僅可以訪問自己的AO,也可以訪問到a的AO,還有全局的GO

b
[[scope]]

scope指向scope chain

scope chain
0 這個位置的0指向自己的AO
1 這個位置的1指向的a的AO
2 這個位置的0指向GO
Activation Object 0指向的是這個表
this window
arguents []
b 234;
Activation Object 1指向的是這個表
this window
arguents []
a 123
b (function)
Global Object 1指向的是這個表
this window
window (object)
document (object)
a (function)
glob 100

作用域銷燬

當b執行完之後,銷燬自己的ao,回到定義狀態,等待下次被執行

因爲b是函數a的最後一句,所以當b執行完之後,a也銷燬掉這麼連帶着b的[[scope]]也被銷燬,回到定義狀態,等待下次被執行

//例子
function a() {
    function b() {
        function c(){

        }
        c();
    }
    b();
}
a();
a defined a.[[scope]] --> 0:GO

a doing   a.[[scope]] --> 0:a的AO
                          1:GO

b defined b.[[scope]] --> 0:a的AO
                          1:GO

b doing   b.[[scope]] --> 0:自己的AO
                          1:a的AO 
                          2:GO

c defined c.[[scope]] --> 0:a的AO
                          1:c的AO 
                          2:GO

c doing   c.[[scope]] --> 0:自己的AO
                          1:b的AO
                          2:a的AO
                          3:GO   
所以外部函數訪問不到內部函數的屬性和值
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章