在以下代码中:
var greeting = "hi";
function changeGreeting() {
if (greeting == "hi") {
var greeting = "hello";
}
alert(greeting);
}
changeGreeting();
... greeting
未定义。但是,如果我删除了var
并将changeGreeting()
更改为:
function changeGreeting() {
if (greeting == "hi") {
greeting = "hello";
}
alert(greeting);
}
......我按照预期得到了“你好”。
我永远不会在我的代码中重新声明这样的变量,但为什么会这样呢?
答案 0 :(得分:27)
JavaScript变量具有函数范围。因此,函数内部var greeting
的存在将声明一个本地greeting
变量,该变量在if
条件提及时将是未定义的:全局变量将不可见在功能内部,被当地人蒙上阴影。因此,if
不会发生,hello
的赋值不会发生,变量仍未定义。
在第二个例子中,你总是使用全局变量,它没有被局部变量所掩盖(因为函数中没有var greeting
),并且事情按预期工作。
答案 1 :(得分:6)
这很简单:JS将变量声明提升到当前作用域的顶部,但不会提升任何操作(包括赋值)(在同一范围内,请参阅第二种情况说明),当然。因此,您的代码段已翻译为
(function()
{
var currentSize;//undefined
if (currentSize == 'hi')//always false
{
currentSize = 'hello';//assignment that will never be
}
alert(currentSize);//alerts undefined, of course
}());
通过省略var,继续进行范围扫描(检查在全局范围内声明的变量)。 遗憾的是,在这样做时,第一次使用var的上下文丢失了(在分支内),并且分配也被提升了。隐含的全局转换为:
感谢上帝,这不是真的。我以为是,因为我在控制台中测试了一些似乎证实这一点的东西。在这种情况下,@ amadan是对的:当我发布这个时,您正在使用全局变量(在您的代码段中称为greeting
)。我将保留下面的代码(更正它)以显示实际上隐含全局变量的内容,希望它有时可以帮助某人理解JS中的范围/范围扫描。
var currentSize = 'hello';
//well, actually implied globals can be deleted, so it's more like
Object.defineProperty(this,'currentSize',{value:undefined,
writable:true,
enumerable:true,
configurable:true});
(function()
{
if (currentSize == 'hi')//always false
{//this still doesn't get executed
currentSize = 'hello';//assignment that will never be
}
alert(currentSize);//alerts undefined
}());
答案 2 :(得分:-1)
在您的第一个代码段中,您正在检查不存在的全局变量 - >如果条件不通过。
在javascript范围以及如何使用变量Javascript garden - function scopes
上查看此内容