要理解變量的作用域范圍就得先理解作用域鏈
用var關鍵字聲明一個變量時,就是為該變量所在的對象添加了一個屬性。
作用域鏈:由於js的變量都是對象的屬性,而該對象可能又是其它對象的屬性,而所有的對象都是window對象的屬性,所以這些對象的關系可以看作是一條鏈
鏈頭就是變量所處的對象,鏈尾就是window對象
看下面的代碼:
function t() { var a; function t2() { var b; } }
js中函數也是對象,所以變量a所在的對象是t,t又在window對象中,所以a的作用域鏈如下
t--window
那么b所以在的對象即t2,t2又包含在t中,t又在window對象,所以b的作用域鏈如下
t2--t--window
明白了作用域鏈下面就開始變量的作用域分析了
1 javascript 沒有var的變量都為全局變量,且為window對象的屬性
function test1() { //執行這個句的時候它會找作用域對象,這個函數就是作用域鏈中的第一個對象,但這個對象中沒有相關的var語句 //於里就找作用域鏈的第二個對象,即全局對象,而全局對象中也沒有相關的var語句 //由於沒有相關的var語句,js隱式在函數地聲明了變量即var all; all = 30; alert(all); } test1(); alert(all); alert(window.all);
2 函數內(函數內的函數除外)定義的變量在整個函數內部都有效
function test2() { var t = 0; //在for的條件里定義變量,這個變更的作用域鏈對象是這個函數 //因此在整個的函數里它是有效的 for (var i = 0; i < 5; i++) { t += i; } alert(i); } test2();
3 函數內部的變量取代全局同名變量
var t = "bb"; function test() { //執行t的時候,它會先找作用域鏈對象,由於它定義在函數內部,所以這個函數就是它的作用域鏈的第一個對象 //而在這個對象里又有t的定義,所以t就是局部變量了,它替換了全局變量t //t只是此時有定義,但並沒有賦值,賦值在下一行,所以這里輸出了undefined alert(t); var t = "aa"; alert(t); } test();
4 沒塊的作用域
if (true) { //在塊中定義了一個變量,它的作用域鏈的第一個對象就是全局對象window var tmp = 0; } //tmp的作用域鏈的第一個對象就是全局對象window,而上面又有全局對象中相關的var語句,因此輸出0 alert(tmp);