【问题标题】:JavaScript scope conflictsJavaScript 范围冲突
【发布时间】:2026-01-03 12:25:01
【问题描述】:

我试图理解 JavaScript 中的作用域。如果我在函数之外声明一个变量,它就是 GLOBAL。因此,我测试了以下代码以了解执行顺序。在下面的代码中,我希望“demo1”采用全局值,即“Volvo”,因为我在函数内声明具有相同名称的局部变量之前渲染了该文本。但令我惊讶的是,我看到该值是“未定义的”。

<!DOCTYPE html>
<html>

<body>
    <p id="demo"></p>
    <p id="demo1"></p>
    <p id="demo2"></p>
    <script>
        var carName = "Volvo";
        myFunction();
        document.getElementById("demo").innerHTML = carName;

        function myFunction() {
            document.getElementById("demo1").innerHTML = carName;
            var carName = "Volvo1";
            document.getElementById("demo2").innerHTML = carName;
        }
    </script>
</body>

</html>

结果:

Volvo

undefined

Volvo1

我进一步修改看看如果在函数内声明另一个全局变量会发生什么,如下所示:

<!DOCTYPE html>
<html>

<body>

    <p id="demo"></p>
    <p id="demo1"></p>
    <p id="demo2"></p>

    <script>
        var carName = "Volvo";
        myFunction();
        document.getElementById("demo").innerHTML = carName;

        function myFunction() {
            document.getElementById("demo1").innerHTML = carName;

            //declaring another global variable
            carName = "Volvo1";
            document.getElementById("demo2").innerHTML = carName;
        }
    </script>
</body>

</html>

结果:

Volvo1

Volvo

Volvo1

这次“demo1”假定在函数外部声明的全局变量,即“Volvo”。

谁能给我解释一下?

【问题讨论】:

标签: javascript html scope variable-declaration hoisting


【解决方案1】:

在 JavaScript 中称为Variable hoisting,定义为:

对于新的 JavaScript 开发人员来说,JavaScript 的一个更棘手的方面是变量和函数被“提升”。

与其在声明后可用,不如说它们可能 实际上是提前可用的。

这意味着您的 carName 变量的第二个 var 声明在函数内排除/消除第一个

因为如果您在代码的全局范围内(代码开头)使用var 关键字声明一个变量,然后重新声明在另一个范围(函数,...)中使用 var 关键字 的相同变量此第二个声明将排除第一个,并且此变量值 成为 undefined.


编辑:

可以看到in the Variable Hoisting section here变量提升的影响以及变量声明变量赋值的区别>:

如果在函数中定义,所有变量声明都被提升(提升和声明)到函数的顶部,如果在函数外部定义,则被提升到全局上下文的顶部。

重要的是要知道只有变量声明被提升到 顶部,不是变量初始化或赋值(当变量 被赋值)。

【讨论】:

  • 好的。但是在第二个代码块中,如果是消除第一个,demo1的值应该是Volvo1而不是“Volvo”(第一个值)。
  • @Sigma,不,因为只有声明被提升。作业保留在它被写入的地方。通过示例查看其他答案
  • 是的,这是预期的结果,它应该是volvo,因为在影响新值之前您正在写信给demo1,请记住您已经删除了 var 关键字,所以它是一个 assignement 而不是 declaration
  • @Sigma 要在评论中回答您的一个问题,如果您不知道变量提升是一个危险的方面,并且所有应用程序都可能因此而损坏,您可以阅读 @987654323 @.
【解决方案2】:

这是由于var 声明的提升。那么myFunction 内部发生的事情实际上是这样的:

function myFunction() {
    // This declaration hides your carName from the outer scope
    var carName; // Var declared here by hoisting
    document.getElementById("demo1").innerHTML = carName; // undefined
    carName = "Volvo1"; // Assigned value
    document.getElementById("demo2").innerHTML = carName;
}

在第二个例子中,你绕过了这个声明

【讨论】:

  • 好的。但是我不得不在函数内部声明一个全局变量。提升有什么用吗?
  • 您可以将carName 内的myFunction 重命名为其他名称吗?毕竟,如果您希望它仅具有函数的范围,那么将其命名为相同是没有意义的。吊装非常有用。实际上,这就是您应该如何编写变量声明的方式,因为它明确显示了声明的变量以及声明的位置。
  • 是的,我知道我可以重命名。由于我正在学习 JS,因此我试图了解它是如何工作的。非常感谢。这对我有帮助。
【解决方案3】:

工作代码:这里是演示http://jsfiddle.net/patelmit69/qa34ky3z/

var carName = "Volvo";
myFunction();
document.getElementById("demo").innerHTML = carName;
function myFunction() {
    document.getElementById("demo1").innerHTML = carName;
    carName = "Volvo1";
    document.getElementById("demo2").innerHTML = carName;
}

【讨论】:

  • @Sigma 请检查您的控制台在执行脚本时是否有任何错误。
【解决方案4】:

这是因为变量提升。变量 declarations 被提升到函数的顶部,因此您的函数的工作方式类似于以下代码:

    function myFunction() {
        var carName; //declaration
        document.getElementById("demo1").innerHTML = carName; // here carName is not defined yet
        carName = "Volvo1"; //assignment
        document.getElementById("demo2").innerHTML = carName;
    }

这就是为什么 #demo1 值未定义的原因。

【讨论】: