JavaScript 通过脚本标签定义作用域

javascript defines scope by script tags?

本文关键字:定义 作用域 标签 脚本 JavaScript      更新时间:2023-09-26

从未遇到过这个问题,也不知道为什么。唯一的解释是范围问题。

在同一页面中,我有 2 个 JS 部分:

...
 <script type="text/javascript">
    go();
  </script>
  <script type="text/javascript">
    function go()
    { alert('');  }
  </script>
...

这将显示一个错误:未定义 go

哪里

...
     <script type="text/javascript">
        go();
        function go()
        { alert('');  }
      </script>
    ...

正在工作(显然)。

<script>标签会创建 JS 的作用域吗?帮助?

这不是范围问题。如果在一个脚本元素中定义函数(在全局范围内),则可以在另一个脚本元素中使用它。

但是,脚本元素在遇到时会进行分析和执行。

提升无法跨脚本元素工作。在较新版本的脚本元素中定义的函数在早期脚本元素的初始运行期间将不可用。

您要么需要交换脚本元素的顺序,要么将函数调用延迟到定义它的脚本运行之后(例如,通过将其附加到onload事件处理程序)。

<script>
    function go() {
        alert('');  
    }
</script>
<script>
    go();
</script>

<script>
    window.addEventListener("load", function () { 
        go();
    }, false);
</script>
<script>
    function go() {
        alert('');  
    }
</script>

html 解析器在移动到下一个元素之前停止执行脚本。所以下一个脚本元素在执行第一个之前不执行。

这相当于:

<script>
document.getElementById("hello") //null because the html parser hasn't met the div yet.
</script>
<div id="hello"></div>

造成明显错误的另一个原因是,如果第一个脚本块存在语法错误并被完全拒绝,但第二个块继续运行并错过其好友代码。

正如已经说过的,顺序很重要。值得一提的是,我在一次实验(不是生产!)中看到了这个问题,我有这样的东西:

<head>
    <script src="/path/one.js" defer>
</head>
<body>
    <script>
        methodInOneJs();
    </script>
</body>

浏览器抱怨引用错误,即使methodInOneJs()在一个.js中定义。这是因为加载它的script中的defer属性。有人可能会认为将defer放在内联script中也可以解决问题,但根据MDN的说法:

警告:如果 src 属性为不存在(即对于内联脚本),在这种情况下,它将没有影响。

一个快速的解决方案(除了完全删除defer之外)是使用 onload 事件(同样,不是生产,我只使用 src):

<head>
    <script src="/path/one.js" defer>
</head>
<body onload="run();">
    <script>
        function run()
        {
            methodInOneJs();
        }
    </script>
</body>

这是因为使用defer

脚本应在文档解析后执行,但在发射 DOMContentLoaded 之前。

强调"在发射 DOMContentLoaded 之前"。另请参阅最后如何加载脚本。