重新声明JavaScript变量

时间:2012-11-29 12:42:32

标签: javascript function scope

在以下代码中:

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);
}

......我按照预期得到了“你好”。

我永远不会在我的代码中重新声明这样的变量,但为什么会这样呢?

3 个答案:

答案 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

上查看此内容