要理解變數的範圍範圍就得先理解範圍鏈
用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);