谁能解释一下,为什么下一个 js 代码会用“string1”文本上升两个警报窗口,而不是用“未定义”文本上升第二个?如果两个变量都在同一范围内描述..
var a = 'string1';
alert(a);
var a;
alert(a);
谢谢
谁能解释一下,为什么下一个 js 代码会用“string1”文本上升两个警报窗口,而不是用“未定义”文本上升第二个?如果两个变量都在同一范围内描述..
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 规范必须说的(加粗强调):
对于代码中的每个VariableDeclaration和VariableDeclarationNoIn d,按源文本顺序执行
- 令dn为d中的标识符。
- 让 varAlreadyDeclared成为调用env 的HasBinding 具体方法并传递dn作为参数的结果。
- 如果varAlreadyDeclared是
false
,那么
- 调用env 的CreateMutableBinding 具体方法,传递dn和 configureBindings作为参数。
- 调用env 的SetMutableBinding 具体方法,传递dn、
undefined
和strict作为参数。
因此,如果已经存在与我们现在尝试绑定的标识符的绑定,则不会发生任何事情。
那是因为 JavaScript 做了一些叫做变量提升的事情。事实上,你的 JS 看起来像这样:
var a; // hoisted -> declared on top
a = 'string1';
alert(a);
alert(a);
有关 JavaScript 工作原理的更多详细信息,请参阅良好的 C# 习惯如何鼓励不良的 JavaScript 习惯。
那是因为第二个var a
不是单独的变量声明。就 javascript 解释器而言,它与第一个解释器相同。
var
表示“将此变量的范围限定为此函数”而不是“将此变量的值设置为undefined
”。
如果变量已经作用于函数,则var foo
意味着与普通的相同foo