JavaScript 作用域(Scope)詳解
先對需要用到的名詞解釋一下,再通過例子深入理解
一、什麼是作用域(Scope)
[[scope]]:每個javascript函式都是一個物件,物件中有些屬性我們可以訪問,但有些不可以,這些屬性僅供javascript引擎存取,[[scope]]就是其中一個。[[scope]]指的就是我們所說的作用域,其中儲存了執行期上下文的集合。即作用域決定了程式碼區塊中變數和其他資源的可見性。
二、變數的作用域型別
1.全域性作用域:全域性作用域貫穿整個javascript文件,在所有函式宣告或者大括號之外定義的變數,都在全域性作用域裡。一旦你聲明瞭一個全域性變數,那麼你在任何地方都可以使用它,包括函式內部。
2.區域性作用域:區域性作用域一般只在固定的程式碼片段內可訪問到,而其外部是無法訪問的,它分為函式作用域和塊級作用域
a:函式作用域: 當你在函式裡定義一個變數時,它在函式內任何地方都可以使用。在函式之外,你就無法訪問它了。
b:塊級作用域:你在使用大括號時,聲明瞭一個const
或者let
的變數時,你就只能在大括號內部使用這一變數。
三、作用域鏈
作用域鏈:[[scope]]中所儲存的執行期上下文物件的集合,這個集合呈鏈式連結,我們把這種鏈式連結叫做作用域鏈。
四、執行期上下文
當函式執行時,會建立一個稱為執行期上下文的內部物件。一個執行期上下文定義了一個函式執行時的環境,函式每次執行時對應的執行上下文都是獨一無二的,所以多次呼叫一個函式會導致建立多個執行上下文,當函式執行完畢,執行上下文被銷燬。(即AO、GO,不瞭解的可參考預預編譯文章)
五、查詢變數
在函式中查詢變數,從其作用域鏈的頂端依次向下查詢,從Scope chain 的0位依次查到最後一位。
通過一個例子具體瞭解上面的定義:
<script> function a() { function b() { var bb = 234 } var aa = 123; b(); } var glob = 100; a(); </script>
1.a()定義時,其Scope裡存放GO
2.a()執行時,形成作用域鏈,Scope chain[0] 存放AO, Scope chain[1] 存放GO
3: b()定義,因為它是a()內部的函式,因此其執行期上下文與a()執行時是一樣的;
4:b()執行時,產生自己的AO,在作用域鏈中將a()的AO與GO儲存位置下移,第0位存自己的AO
注意:b() Scope chain 儲存的a() 的AO與a()中的AO一樣,只是將其引用掛到裡面,即通過b()中可以改變a()中變數的值
例:
<script> function a() { function b() { var bb = 234 aa = 0; } var aa = 123; b();
console.log(a); } var glob = 100; a(); </script>
輸出a的值為 0