2012-07-26 71 views
5

任何人都可以解釋爲什麼下一個js代碼在'string1'文本中上升兩個警告窗口,而不是在'undefined'文本內部升起第二個警告窗口?如果兩個變量都在相同的範圍中記載..在全球範圍內使用相同名稱定義的變量

var a = 'string1'; 
alert(a); 
var a; 
alert(a);​ 

http://jsfiddle.net/FdRSZ/1/

感謝

+0

+1,有趣的問題。 – 2012-07-26 14:04:08

+0

局部變量也應該具有相同的行爲。 – hugomg 2012-07-26 14:09:02

回答

6

變量聲明(和函數聲明)相同的是懸掛在它們出現的範圍的頂部。分配發生在適當的位置。該代碼是有效的解釋是這樣的:

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不得不說(粗體強調):

對於每個VariableDeclarationVariableDeclarationNoIn d代碼,在 源文本排序做

  • dn標識符 in d
  • varAlreadyDeclared是調用env的 HasBinding具體 方法傳遞DN作爲參數的結果。
  • 如果varAlreadyDeclaredfalse,然後
    • 呼叫env的 CreateMutableBinding傳遞DNconfigurableBindings作爲參數具體方法。
    • 呼叫env的 SetMutableBinding傳遞DNundefined,並嚴格作爲參數具體方法。

因此,如果結合已經與我們正在努力現在綁定的標識存在,沒有任何反應。

3

這是因爲第二var a是不是一個獨立的變量聲明。就JavaScript解釋器而言,它與第一個相同。

3

var表示「將此變量作用於此函數」而不是「將此變量的值設置爲undefined」。

如果變量已經作用域到函數然後var foo係指只是簡單foo

4

那是因爲JavaScript做了一件叫做變量提升。事實上,你的JS是這樣的:

var a; // hoisted -> declared on top 

a = 'string1'; 
alert(a); 
alert(a); 

對JavaScript的是如何工作的詳細信息,請參見How Good C# Habits can Encourage Bad JavaScript Habits

+0

感謝您的鏈接,一個有用的 – 2012-07-26 14:19:11

相關問題