作用域
js看似有”塊級作用域“其實它沒有,取而代之的是“函數作用域”。
塊級作用域:
在一個代碼塊(一對花括號內)定義的變量在代碼塊外部是不可見的,且在代碼塊執行結束後被釋放掉。
函數作用域:
定義在該函數中的參數和變量在函數外部不可見(例子1),而一個函數內部任何位置定義的變量,在該函數內部任何地方都可見(例子2)。
解釋二:也就是說,變量不僅在聲明它們的函數體內有定義,還在這個函數體嵌套的任意函數體內都有定義。(例子1裏的d)
例子1
var foo=function(){
var a=3,b=5,d=2;
var bar=function(){
var b=7,c=11;
document.writeln('1.bar內的a='+a+'b='+b+'c='+c+'d='+d+'<br>');
a=b+c;
document.writeln('2.bar內的a='+a+'b='+b+'c='+c+'<br>');
};
document.writeln('3.foo內的a='+a+'b='+b+'<br>');//c無定義
bar();
document.writeln('4.foo內的a='+a+'b='+b+'<br>');//c無定義
}
foo();
//運行結果
3.foo內的a=3 b=5
1.bar內的a=3 b=7 c=11 d=2
2.bar內的a=21 b=7 c=11
4.foo內的a=21 b=5
例子2:
var o={};
function test(o){
var i=0; //i在整個函數體內有定義
if(typeof o=="object"){
var j=1; //j在函數體內有定義,不僅是在這個代碼塊內
for(var k=0;k<2;k++){ //k在函數體內有定義,不僅僅是在這個循環體內
console.log(k); //輸出數字0-1
}
console.log(k); //k已經定義了,輸出2
}
console.log(j); //j已經定義了,且已初始化爲1
console.log("我是循環裏的k="+k); //我是循環裏的k=2
}
聲明提前
變量在聲明之前就已經可用。
例子:
var scope="global";
function f(){
console.log(scope);// 輸出undefined而不是global
var scope="local"; //變量在這裏被賦值 ,但是變量本身在函數體任何地方都有定義
console.log(scope);//輸出 local
}
也就是:將變量的聲明“提前”到函數頂部,同時變量初始化留在原來的位置。
function f(){
var scope;
console.log(scope);
var scope="local";
console.log(scope);//輸出 local
作用域鏈
遍歷嵌套作用域鏈的規則很簡單:引擎從當前的執行作用域開始查找變量,如果找不到, 就向上一級繼續查找。當抵達最外層的全局作用域時,無論找到還是沒找到,查找過程都 會停止。