先對需要用到的名詞解釋一下,再通過例子深入理解 一、什麼是作用域(Scope) [[scope]]:每個javascript函數都是一個對象,對象中有些屬性我們可以訪問,但有些不可以,這些屬性僅供javascript引擎存取,[[scope]]就是其中一個。[[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