【问题标题】:Redeclare JavaScript Variable重新声明 JavaScript 变量
【发布时间】:2012-11-29 12:42:32
【问题描述】:

在以下代码中:

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

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

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

【问题讨论】:

    标签: javascript function scope


    【解决方案1】:

    JavaScript 变量具有函数作用域。因此,函数内部var greeting 的存在将声明一个局部greeting 变量,在if 条件中提到它时将未定义:全局变量在函数内部将不可见,被掩盖由当地人。因此,if 不会发生,hello 的赋值不会发生,变量仍然未定义。

    在第二个示例中,您始终使用全局变量,它不会被局部变量所掩盖(因为函数内部没有 var greeting),并且一切正常。

    【讨论】:

    • @bfavaretto:我认为var greeting 是一个错误,并且应该是var currentSize 全局变量声明(在第一个示例中会被掩盖,并在第二个示例中使用)。否则它将与示例完全无关。
    • @Amadan - 我很抱歉这是一个错误。这是从另一个 SO 答案中复制的并进行了精简,我错过了变量命名不一致。再次感谢您的回答——我知道这个问题会得到很大的分数;)。
    • @levib:不用担心,会发生的。 :)
    • @Amadan 抱歉,我很快就意识到了这一点,并删除了我的评论。
    • 所以变量在被声明之前就被使用了,因为有一种预处理器!!!感谢您的回答
    【解决方案2】:

    很简单:JS将变量声明提升到当前作用域的顶部,但是任何操作(包括赋值)都不会被提升(在同一作用域内,见第二种情况解释),当然。所以你的 sn-p 被翻译成

    (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 是对的:您正在使用全局变量(当我发布此内容时,您的 sn-p 中错误地称为 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
    }());
    

    【讨论】:

    • 关于变量作用域的一个很好解释的答案我从中学到了很多东西来纠正我关于 JS 中变量作用域的概念
    【解决方案3】:

    在您的第一个代码 sn-p 中,您正在检查全局变量,该变量不存在 -> 不通过 if 条件。

    查看 javascript 作用域以及如何使用变量 Javascript garden - function scopes

    【讨论】:

    • 第一个 sn-p not 检查全局变量,函数体包含该变量的 var 声明,该变量被提升到顶部。它正在检查一个本地 var currentLength;
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多