任何人都可以解釋爲什麼下一個js代碼在'string1'文本中上升兩個警告窗口,而不是在'undefined'文本內部升起第二個警告窗口?如果兩個變量都在相同的範圍中記載..在全球範圍內使用相同名稱定義的變量
var a = 'string1';
alert(a);
var a;
alert(a);
感謝
任何人都可以解釋爲什麼下一個js代碼在'string1'文本中上升兩個警告窗口,而不是在'undefined'文本內部升起第二個警告窗口?如果兩個變量都在相同的範圍中記載..在全球範圍內使用相同名稱定義的變量
var a = 'string1';
alert(a);
var a;
alert(a);
感謝
變量聲明(和函數聲明)相同的是懸掛在它們出現的範圍的頂部。分配發生在適當的位置。該代碼是有效的解釋是這樣的:
var a;
var a;
a = 'string1';
例如,考慮如果聲明的if
聲明體內的變量會發生什麼:
console.log(myVar); //undefined (NOT a reference error)
if (something === somethingElse) {
var myVar = 10;
}
console.log(myVar); //10
因爲JavaScript沒有塊範圍,所有聲明中每個範圍都被提升到該範圍的頂部。如果你試圖記錄一些未聲明的變量,你會得到一個參考錯誤。上面的例子這樣解釋:
var myVar; //Declaration is hoisted
console.log(myVar);
if (something === somethingElse) {
myVar = 10; //Assignment still happens here
}
console.log(myVar);
所以,即使條件評估爲false
,該myVar
變量仍然可以訪問。這是JSLint會告訴您將所有聲明移到它們出現的範圍頂部的主要原因。
稍微詳細...這是什麼ECMAScript 5 spec不得不說(粗體強調):
對於每個VariableDeclaration和VariableDeclarationNoIn d在代碼,在 源文本排序做
- 讓dn是標識符 in d。
- 讓 varAlreadyDeclared是調用env的 HasBinding具體 方法傳遞DN作爲參數的結果。
- 如果varAlreadyDeclared是
false
,然後
- 呼叫env的 CreateMutableBinding傳遞DN和 configurableBindings作爲參數具體方法。
- 呼叫env的 SetMutableBinding傳遞DN,
undefined
,並嚴格作爲參數具體方法。
因此,如果結合已經與我們正在努力現在綁定的標識存在,沒有任何反應。
這是因爲第二var a
是不是一個獨立的變量聲明。就JavaScript解釋器而言,它與第一個相同。
var
表示「將此變量作用於此函數」而不是「將此變量的值設置爲undefined
」。
如果變量已經作用域到函數然後var foo
係指只是簡單foo
那是因爲JavaScript做了一件叫做變量提升。事實上,你的JS是這樣的:
var a; // hoisted -> declared on top
a = 'string1';
alert(a);
alert(a);
對JavaScript的是如何工作的詳細信息,請參見How Good C# Habits can Encourage Bad JavaScript Habits。
感謝您的鏈接,一個有用的 – 2012-07-26 14:19:11
+1,有趣的問題。 – 2012-07-26 14:04:08
局部變量也應該具有相同的行爲。 – hugomg 2012-07-26 14:09:02