2012-07-26 63 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

相关问题