大多數語言里面都會使用{}
來形成一個作用域,俗稱塊級作用域。JavaScript中{}
沒有帶來塊級作用域,JavaScript的作用域是靠函數來形成的,也就是說一個函數內定義的變量,函數外不可以訪問。
function fn() {
var a =1;
if(a > 2) {
var b = 3;
}
console.log(b);
}
fn(); //undefined
console.log(a); //輸出undefined
有了作用域的概念,函數間的層層引用時,每個變量所屬的作用域都是確定的,那同名的變量應該如何確定引用關系呢?比如:
var a = 1
function fn1(){
function fn2(){
console.log(a)
}
function fn3(){
var a = 4
fn2()
}
var a = 2
return fn3
}
var fn = fn1()
fn() //輸出2
為什么最后輸出是2?當某個函數被調用時,會創建一個執行環境及相應的作用域鏈。fn2執行時,作用域鏈是:fn2() -> fn3() -> window。fn2內部沒有定義變量a,所以會從它聲明的環境中查找,而不是調用的環境。所以找到的是var a = 2;
解密:
- 函數在執行的過程中,先從自己內部找變量
- 如果找不到,再從創建當前函數所在的作用域去找, 以此往上
- 注意找的是變量的當前的狀態
P.S. 聲明提前在作用域下同樣適用。復雜情況一定要考慮進去。