为什么在外部范围内定义时,阴影变量评估为未定义?

IT技术 javascript variables shadowing
2021-03-17 21:11:34

考虑下面的一段代码:

<html><head></head>
<body>
    <script type="text/javascript">
        var outside_scope = "outside scope";
        function f1() {
            alert(outside_scope) ;
        }
        f1();
    </script>
</body>
</html> 

此代码的输出是警报框显示消息“超出范围”。但是,如果我将代码稍微修改为:

<html><head></head>
<body>
    <script type="text/javascript">
        var outside_scope = "outside scope";
        function f1() {
            alert(outside_scope) ;
            var outside_scope = "inside scope";
        }
        f1();
    </script>
</body>
</html> 

警报框显示消息“未定义”。如果在这两种情况下都显示“未定义”,我本可以理解逻辑。但是,这不会发生。它仅在第二种情况下显示“未定义”。为什么是这样?

在此先感谢您的帮助!

6个回答

变量会被提升这意味着无论变量在函数中的什么位置,它都会被移动到定义它的作用域的顶部。

例如:

var outside_scope = "outside scope";
function f1() {
    alert(outside_scope) ;
    var outside_scope = "inside scope";
}
f1();

被解释为:

var outside_scope = "outside scope";
function f1() {
    var outside_scope; // is undefined
    alert(outside_scope) ;
    outside_scope = "inside scope";
}
f1();

正因为如此,以及 JavaScript 所具有的唯一作用域,建议在函数顶部声明所有变量,以类似于将要发生的情况。

多年后我不知道这一点,也许是因为我总是在顶部声明,就像在 C 中一样。
2021-04-23 21:11:34

在第一种情况下,您的代码正在访问全局变量“outside_scope”,该变量已初始化为“外部范围”。

Javascript 具有函数级作用域,因此在第二种情况下,它访问的是函数作用域变量“outside_scope”,但在出现警告框时尚未初始化。所以它显示未定义。

JavaScript 有函数作用域,而不是块作用域。

在第二种情况下,outside_scope 的声明被提升到函数的顶部(但赋值不是)。

这是一个很好的例子,说明如果将所有变量声明放在函数顶部,JavaScript 代码更易于阅读。你的第二个例子相当于:

function f1() {
    var outside_scope;
    alert(outside_scope);
    outside_scope = "inside scope";
}

并且您现在可能会理解为什么您会“未定义”。

在第二个示例中,局部变量存在于整个函数范围内。在警报之后定义它并不重要,它存在于整个函数中。

但是,实际分配直到警报之后才会发生,因此是“未定义”。

这是由于所谓的变量声明提升

基本上,JavaScript将变量声明分为两部分,将赋值留在您进行声明的地方,并将实际声明提升到函数的顶部

var f1 = function ()  {
   // some code
   var counter = 0;
   // some more code
}

var f2 = function () {
   var counter; // initialized with undefined
   // some code
   counter = 0;
   // some more code
}

在运行时,f1()被翻译成f2(). 我在这里写了一篇关于此的深入博客文章我希望这可以帮助您了解代码中发生的事情。

这也是原因,建议在 JavaScript中的函数顶部声明您的变量它可以帮助您了解代码在运行时的作用。