为什么在之后创建的变量上使用 console.log( 但在另一个脚本标签中出现错误而不是在控制台中记录“未定义”时?[复制]

why when using console.log() on a variable created afterwards but in another script tag i get an error instead of logging 'undefined' in the console? [duplicate]

提问人:Mahmoud Fathy 提问时间:7/15/2023 更新时间:11/20/2023 访问量:37

问:

为什么此代码片段会在控制台中显示错误“Uncaught ReferenceError: x is not defined”"

<body>
    <script>
        console.log(x);
    </script>
    
    <script>
        var x = 10;
    </script>
</body>

而这个记录“未定义”?

<body>
    <script>
        console.log(x);
        var x = 10;
    </script>
</body>

我试图了解变量声明和变量范围。并预计会发生吊装,因为整个代码位于同一页面中。但是由于 console.log() 在另一个 scirpt 标签中分离,我得到了一个错误,而不仅仅是在控制台中记录“未定义”。

JavaScript 变量 作用域 控制台 .log 提升

评论

0赞 Rory McCrossan 7/15/2023
研究变量吊装
0赞 Bergi 7/15/2023
"因为控制台.log()在另一个scirpt标签中是分开的,所以我得到了一个错误而不是[提升]“ - 似乎你已经回答了自己的问题
0赞 traktor 7/15/2023
实际的答案不是特别关于可变提升。您有一个计时错误 - 在执行第一个脚本之前,第二个脚本标记尚未被处理(解析和执行)。JavaScript 引擎在编译和执行第一个脚本时,对第二个脚本中的文件级声明一无所知
0赞 traktor 8/1/2023
自这个问题以来,MDN 上的 var 文章已经更新。希望对 和 部分所做的更改(后者带有涵盖问题标题的注释)现在更好地回答您的帖子。DescriptionHoisting

答:

2赞 Alexander Nenashev 7/15/2023 #1

var被吊起,这意味着它可以在定义它的作用域的开头访问,甚至声明行也可能在作用域的末尾。如果您在声明之前访问 var,那是因为您仍然需要执行声明,并可能将此变量初始化为特定值。 所以你的第二个例子就是这样工作的。undefined

在此处阅读有关吊装的信息:

https://developer.mozilla.org/en-US/docs/Glossary/Hoisting

但是在您的第一个示例中,2 有 2 个不同的范围,因此 var 在第一个脚本中基本上不存在,因此出现错误。<scripts>not defined

在此处阅读及其范围:var

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var

重要我强烈反对使用 .请改用 and。与吊装一起使用会导致错误,有时很难调试和修复。如果您只需要在生产中使用,只需使用 esbuild 将代码降级到适当的旧版本 JS。varconstletvarvar

有趣的是,它们也有点被吊起,但是在吊起状态下访问它们会导致运行时错误(这称为时间死区),这就是为什么它们更安全的原因,因为您会立即收到一个错误,而不是静默地吊起,从而给您留下一个您不知道的潜在错误。constletvar

关于时间死区:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let#temporal_dead_zone_tdz

<body>
    <script>
        console.log(x);
        const x = 10;
    </script>
</body>

一个有趣的部分:这 2 个 s 是按出现的顺序执行的,但如果你通过延迟它来改变顺序(在 DOM 构建后执行),那么你就会得到定义的变量。这是延迟内联脚本的唯一方法,因为不起作用:<script>type="module"defer

https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script

<body>
    <script type="module">
        console.log(x);
    </script>
    
    <script>
        var x = 10;
    </script>
</body>