作用域:在js預編譯時、代碼執行之前對全局或局部的變數進行收集,存放在一指定記憶體中scope,執行時對scope進行訪問,scope 就是全局或局部的作用域。 如: 1 function test() { 2 var a = 123; 3 } 4 5 test(); 在test() 執行之前對tes ...
作用域:在js預編譯時、代碼執行之前對全局或局部的變數進行收集,存放在一指定記憶體中scope,執行時對scope進行訪問,scope 就是全局或局部的作用域。
如:
1 function test() { 2 var a = 123; 3 } 4 5 test();
在test() 執行之前對test 進行預編譯 生成test 的 scope(AO Activetion Object)。收集test 函數中的變數存放在scope中。
此時test 的scope 為:
{
a:undefined
}
在test 函數執行時 對 scope 中的 a 變數進行賦值,a = 123;
實際上在全局環境進行預編譯時也會產生一個作用域,在test 被定義時會在test 函數上定義一個作用域數組([[Scopes]])。並將全局作用域放入test的作用域數組中。
如:
1 var a = 456; 2 3 function test() { 4 var b = 123; 5 console.log(b); 6 console.log(a); 7 } 8 9 test();
在全局環境進行預編譯時,會生成全局作用域Global
Global {
a: undefined,
test: undefined
}
此時test 函數的作用域數組中就已經包含了Global
test.[[Scopes]] = [Global] // 實際上[[Scopes]] 是不可訪問的
全局環境執行完後Global變成
Global{
a: 456,
test: function test() {...}
}
在test 函數執行前會對test函數進行預編譯,生成test 函數的scope並放入到test 函數的作用域數組的第一位。
scope {
b: undefined
}
test.[[Scopes]] = [scope,Global] // 實際上[[Scopes]] 是不可訪問的
在test 代碼執行b= 123時對作用域scope 中的b進行賦值
scope {
b: 123
}
在test 函數中列印a 時會沿著test 作用域數組中的順序進行查找,首先會查找test 的scope 中是否有a,如果有者直接使用,如果沒有沿著[[Scopes]] 繼續查找,在Global 中進行查找,所以列印的是Global 中的a的值--456。
如果沿著[[Scopes]] 的順序找到Global 一直找不到a,就會報錯 a is not defined。
由於在訪問變數時會沿著[[Scopes]] 查找,這種查找機制類似鏈條結構,所以稱[[Scopes]] 為作用域鏈。