範圍
範圍是JavaScript中一個較難處理的特性。所有物件導向的程式設計語言都有某種形式的範圍;這要看是什麼上下文約束著範圍。在JavaScript裡,範圍由函數約束,而不由塊約束(如while,if,和for裡的語句體)。最終可能使得一些代碼的運行結果表面上顯得怪異(如果你來自一種塊範圍語言的話)。程式2-10的例子說明了“函數範圍代碼”的含義。
代碼2-10. JavaScript中變數範圍是怎樣工作的例子
//設定一個等於"test"的全域變數foo
var foo = "test";
//在if塊中
if ( true ) {
//設定foo為"new test"
//注意:這仍然是在全域範圍中
var foo = "new test";
}
//正如我們在此處可見,foo現在等於"new test"
alert( foo == "new test" );
//建立一個修改變數foo的函數
function test() {
var foo = "old test";
}
//調用時,foo卻駐留在是在函數的範圍裡面
test();
//確認一下,foo的值仍然是"new test"
alert( foo == "new test" );
在程式2-10中你會發現,變數位於在全域範圍。基於瀏覽器的JavaScript有趣的一面是,所有的全域變數實際上都是window對象的屬性。儘管一些老版本的Opera瀏覽器或Safari瀏覽器不是這樣,假定瀏覽器這樣工作通常是一個很好的經驗規則。程式2-11展示了一個這種例子。
程式2-11. JavaScript的全域變數與window對象的例子
//全域變數,包含字串"test"
var test = "test";
//你會發現,我們的全域變數和window的test屬性是相同的
alert( window.test == test );
最後,讓我們來看看當一個變數漏定義時會怎樣。程式2-12裡,變數foo在test()的範圍裡被賦值。但是,程式2-12裡實際並沒有(用var foo)定義變數的範圍。當變數foo沒有明確定義時,它將成為全域變數,即使它只在函數的上下文使用。
程式2-12. 隱式全域變數聲明的樣本
//一個為變數foo賦值的函數
function test() {
foo = "test";
}
//調用函數為foo賦值
test();
//我們發現foo現在是全域變數了
alert( window.foo == "test" );
到目前應該很明顯,儘管JavaScript的範圍不如塊範圍語言的嚴格,它還是相當強大和有特色的。尤其是與下節中敘述的閉包的概念結合起來時,JavaScript語言的強大將展露無遺。