首页 > 解决方案 > 在什么情况下 HTML 标记中的 script 标签可以包含在 head 标签中而不使用 async 和 defer 属性?

问题描述

大家好,我是 JavaScript 和 Web 开发的新手。我最近遇到了这个关于脚本标签位置的问题。我知道这是一个常见问题,我在 stackoverflow 上查看了一些答案,也在 google 上查看了这个样式指南。但我对这个问题仍然不是很清楚。

例如,我有一个带有这样的外部脚本 js 文件的 html 页面

<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title></title>
    <script src='js.js'>
    </script>
  </head>
  <body>
  </body>
</html>

js文件是

var loadTime = document.createElement('div');
loadTime.textContent = 'You loaded this page on: ' + new Date();
loadTime.style.color = 'blue';
document.body.appendChild(loadTime);

在我看来,这个 js 文件不依赖于可用的 html 文件的任何 DOM 元素,所以我把这个脚本标签放在哪里并不重要。但事实证明,我必须将此脚本标记放在正文结束标记的底部,否则日期不会按预期显示在页面上。另一种解决方法是在脚本标签中使用 defer 属性,如下所示

<script src='js.js' defer></script>

这让我感到困惑,如果一个脚本有任何与 DOM 相关的操作,在我看来,如果没有 defer 或 async 属性,它就不能放在前面的 head 标签内。为什么这个 google 风格指南https://developers.google.com/speed/docs/insights/BlockingJS仍然建议我们可以在 head 标签中编写内联脚本,因为访问和操作 DOM 在任何脚本文件中都非常常见。

根据 http://caniuse.com/#feat=script-defer,94.59% 的浏览器都支持这一点。94.92% 至少部分支持它。为什么 async 和 defer 属性没有被广泛使用?我的意思是,我查看了很多 HTML 源代码,但我只是没有在任何地方看到 async 和 defer 属性?

标签: javascripthtmlweb

解决方案


所以这里有一些解释。

  1. 在没有任何额外属性的情况下在 HTML 中使用<script></script>将阻止 HTML 解析(换句话说,“将 html 加载到浏览器窗口”)。成功下载后,将获取并执行指定的脚本。之后,将恢复执行(将加载页面)。
  2. 使用<script async></script>允许 HTML 解析器在下载脚本之前不会阻止解析。
  3. 使用<script defer></script>允许 HTML 被完全解析,然后脚本代码将被执行。

因此,从主题中回答您的问题 -<head></head>如果脚本不需要访问尚不存在的内容,则可以包含其中的脚本(并且可以正常工作)。在您的示例中,您试图将 sth 附加到 body (尚不存在)。如果您正在使用<script async></script><head></head>也不能保证工作。例如。脚本很小(几乎可以立即下载)——它将在 html 完全解析之前执行(导致访问尚未存在的内容)。我们可以为异步请求计时,这是它们美丽的一部分。

如果获取的脚本不能直接访问 DOM,则使用 async 是有意义的。

使用 defer 是有意义的,例如。如果 JS 文件很大(例如 fetch 需要 5 秒)并且我们想向用户显示某事。在页面上。加载脚本后,我们通过脚本中的 js 将页面更改为它的 inteded 'look'。

请注意,这些并不是 async 和 defer 的所有用例。


推荐阅读