测验

描述 `<script>`、`<script async>` 和 `<script defer>` 之间的区别

主题
HTMLJavaScript
在GitHub上编辑

TL;DR

所有这些方式(<script><script async><script defer>)都用于在 HTML 文档中加载和执行 JavaScript 文件,但它们在浏览器处理脚本的加载和执行方式上有所不同:

  • <script> 是包含 JavaScript 的默认方式。浏览器在下载和执行脚本时会阻止 HTML 解析。在脚本执行完毕之前,浏览器不会继续渲染页面。
  • <script async> 异步下载脚本,与解析 HTML 并行。在脚本可用后立即执行脚本,可能会中断 HTML 解析。<script async> 之间不会互相等待,并且以不特定的顺序执行。
  • <script defer> 异步下载脚本,与解析 HTML 并行。但是,脚本的执行被推迟到 HTML 解析完成后,按照它们在 HTML 中出现的顺序。

这是一个表格,总结了在 HTML 文档中加载 <script> 的 3 种方式。

特性<script><script async><script defer>
解析行为阻止 HTML 解析与解析并行运行与解析并行运行
执行顺序按照出现顺序不保证按照出现顺序
DOM 依赖是(等待 DOM)

<script> 标签的用途

<script> 标签用于在网页中包含 JavaScript。asyncdefer 属性用于更改脚本的加载和执行方式/时间。

<script>

对于没有任何 asyncdefer 的普通 <script> 标签,当遇到它们时,HTML 解析会被阻止,脚本会被立即获取和执行。HTML 解析在脚本执行完毕后恢复。如果脚本很大,这可能会阻止页面的渲染。

<script> 用于页面依赖于正确渲染的关键脚本。

<!doctype html>
<html>
<head>
<title>Regular Script</title>
</head>
<body>
<!-- Content before the script -->
<h1>Regular Script Example</h1>
<p>This content will be rendered before the script executes.</p>
<!-- Regular script -->
<script src="regular.js"></script>
<!-- Content after the script -->
<p>This content will be rendered after the script executes.</p>
</body>
</html>

<script async>

<script async> 中,浏览器异步下载脚本文件(与 HTML 解析并行),并在脚本可用后立即执行(可能在 HTML 解析完成之前)。执行不一定按照它在 HTML 文档中出现的顺序执行。这可以提高感知的性能,因为浏览器在继续渲染页面之前不必等待脚本下载。

当脚本独立于页面上的任何其他脚本时,使用 <script async>,例如分析和广告脚本。

<!doctype html>
<html>
<head>
<title>Async Script</title>
</head>
<body>
<!-- Content before the script -->
<h1>Async Script Example</h1>
<p>This content will be rendered before the async script executes.</p>
<!-- Async script -->
<script async src="async.js"></script>
<!-- Content after the script -->
<p>
This content may be rendered before or after the async script executes.
</p>
</body>
</html>

<script defer>

<script async> 类似,<script defer> 也会与 HTML 解析并行下载脚本,但脚本仅在文档被完全解析并且在触发 DOMContentLoaded 之前执行。如果有多个,则每个延迟脚本按照它们在 HTML 文档中出现的顺序执行。

如果脚本依赖于完全解析的 DOM,则 defer 属性将有助于确保在执行之前完全解析 HTML。

<!doctype html>
<html>
<head>
<title>Deferred Script</title>
</head>
<body>
<!-- Content before the script -->
<h1>Deferred Script Example</h1>
<p>This content will be rendered before the deferred script executes.</p>
<!-- Deferred script -->
<script defer src="deferred.js"></script>
<!-- Content after the script -->
<p>This content will be rendered before the deferred script executes.</p>
</body>
</html>

注意事项

  • async 属性应用于对页面初始渲染不关键且彼此不依赖的脚本,而 defer 属性应用于依赖于/被另一个脚本依赖的脚本。
  • 对于没有 src 属性的脚本,将忽略 asyncdefer 属性。
  • 包含 document.write() 的带有 deferasync<script> 将被忽略,并显示类似“从异步加载的外部脚本对 document.write() 的调用被忽略”的消息。
  • 即使 asyncdefer 有助于使脚本下载异步,但脚本最终仍在主线程上执行。如果这些脚本是计算密集型的,则可能导致 UI 滞后/冻结。Partytown 是一个库,它有助于将脚本执行重新定位到 web worker 并从 主线程 中移出,这对于您无法控制代码的第三方脚本非常有用。

延伸阅读

在GitHub上编辑