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

问题描述 投票:0回答:1

为什么此代码片段会在控制台中给出错误“Uncaught ReferenceError:x未定义

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

而这个记录“未定义”?

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

我试图了解变量声明和变量作用域。并预计会发生提升,因为整个代码都在同一页面中。但是因为 console.log() 被分开在另一个脚本标记中,所以我得到了一个错误,而不是仅仅在控制台中记录“未定义”。

javascript variables scope console.log hoisting
1个回答
2
投票

var
被提升,这意味着它可以在定义它的范围的开头访问,即使声明行可能位于范围的末尾。如果您在声明之前访问 var,那么它是
undefined
,因为您仍然需要执行声明并可能将此变量初始化为特定值。 所以你的第二个例子就是这样工作的。

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

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

但是在第一个示例 2

<scripts>
有 2 个不同的作用域,因此 var 基本上不存在于第一个脚本中,因此出现错误
not defined

在此处了解

var
及其范围:

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

重要 我强烈反对使用

var
。请改用
const
let
。使用
var
进行提升会导致错误,有时很难调试和修复。如果您在生产中只需要使用
var
,只需使用 esbuild 将代码降级到适当的旧版本 JS。

有趣的是,

const
let
也被提升了,但是在提升状态下访问它们会导致运行时错误(称为临时死区),这就是为什么它们更安全,因为你会收到错误立即反对 var 默默地提升,从而给你留下一个你不知道的潜在错误。
关于颞死区:

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 个

<script>

按出现的顺序执行,但是如果您通过使用

type="module"
推迟它(在构建 DOM 后执行)来更改顺序,那么您将获得定义的变量。这是推迟内联脚本的唯一方法,因为
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>

© www.soinside.com 2019 - 2024. All rights reserved.