5

谁能解释一下,为什么下一个 js 代码会用“string1”文本上升两个警报窗口,而不是用“未定义”文本上升第二个?如果两个变量都在同一范围内描述..

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

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

谢谢

4

4 回答 4

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 规范必须说的(加粗强调):

对于代码中的每个VariableDeclarationVariableDeclarationNoIn d,按源文本顺序执行

  • dnd中的标识符
  • varAlreadyDeclared成为调用env 的HasBinding 具体方法并传递dn作为参数的结果。
  • 如果varAlreadyDeclaredfalse,那么
    • 调用env 的CreateMutableBinding 具体方法,传递dnconfigureBindings作为参数。
    • 调用env 的SetMutableBinding 具体方法,传递dnundefinedstrict作为参数。

因此,如果已经存在与我们现在尝试绑定的标识符的绑定,则不会发生任何事情。

于 2012-07-26T14:03:03.127 回答
4

那是因为 JavaScript 做了一些叫做变量提升的事情。事实上,你的 JS 看起来像这样:

var a; // hoisted -> declared on top

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

有关 JavaScript 工作原理的更多详细信息,请参阅良好的 C# 习惯如何鼓励不良的 JavaScript 习惯

于 2012-07-26T14:03:12.567 回答
3

那是因为第二个var a不是单独的变量声明。就 javascript 解释器而言,它与第一个解释器相同。

于 2012-07-26T14:02:30.467 回答
3

var表示“将此变量的范围限定为此函数”而不是“将此变量的值设置为undefined”。

如果变量已经作用于函数,则var foo意味着与普通的相同foo

于 2012-07-26T14:02:37.783 回答