任何人都可以解释为什么下一个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