js:函數中的作用域和作用域鏈

作用域

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

作用域鏈

遍歷嵌套作用域鏈的規則很簡單:引擎從當前的執行作用域開始查找變量,如果找不到, 就向上一級繼續查找。當抵達最外層的全局作用域時,無論找到還是沒找到,查找過程都 會停止。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章