面试题之:script标签中defer和async的区别

deferasync<script> 标签的两个属性,它们都用于控制外部脚本(带有 src 属性的脚本)的加载和执行方式,以避免阻塞 HTML 文档的解析。它们的主要区别在于脚本的执行时机

核心区别

特性deferasync
执行时机在 HTML 文档解析完成后,DOMContentLoaded 事件触发之前执行。在脚本下载完成后立即执行,无论此时 HTML 文档是否解析完毕。
执行顺序保证顺序。多个带有 defer 的脚本会按照它们在文档中出现的顺序依次执行。不保证顺序。每个脚本在下载完成后就立即执行,因此执行顺序取决于哪个脚本先下载完,与它们在文档中的顺序无关。
与 DOM 的关系脚本执行时,整个 DOM 树已经构建完毕,可以安全地访问和操作 DOM 元素。脚本执行时,DOM 树可能尚未完全构建完毕,因此直接操作 DOM 可能有风险(需要检查 DOM 状态或监听 DOMContentLoaded)。
与 DOMContentLoaded 的关系所有 defer 脚本的执行都早于 DOMContentLoaded 事件。async 脚本的执行时间不确定,可能在 DOMContentLoaded 之前、之后,或者正好同时。

图解执行流程

假设 HTML 文档中有多个 <script> 标签:


<html>
<head>
  <script src="script1.js" defer></script>
  <script src="script2.js" defer></script>
  <!-- 或者 async -->
  <script src="scriptA.js" async></script>
  <script src="scriptB.js" async></script>
</head>
<body>
  <div id="content">页面内容</div>
  <!-- HTML 解析继续 -->
</body>
</html>
  • defer 流程

    1. 浏览器开始解析 HTML。
    2. 遇到 script1.js 和 script2.js异步开始下载这两个文件,不阻塞  HTML 解析。
    3. 继续解析 HTML,构建 DOM。
    4. HTML 文档解析完成,按顺序执行 script1.js,然后执行 script2.js
    5. 触发 DOMContentLoaded 事件。
  • async 流程

    1. 浏览器开始解析 HTML。
    2. 遇到 scriptA.js 和 scriptB.js异步开始下载这两个文件,不阻塞 HTML 解析。
    3. 假设 scriptA.js 先下载完,立即暂停 HTML 解析并执行 scriptA.js
    4. scriptA.js 执行完毕后,继续解析 HTML。
    5. 当 scriptB.js 下载完时,立即暂停 HTML 解析并执行 scriptB.js(即使此时 HTML 还没解析完)。
    6. 最终 HTML 文档解析完成,触发 DOMContentLoaded 事件

如何选择?

  • 使用 defer

    • 当你的脚本依赖于完整的 DOM 结构(例如,需要操作页面上的元素)。
    • 当你有多个脚本,并且它们之间有依赖关系,需要按顺序执行(例如,先加载 jQuery,再加载依赖 jQuery 的插件)。
    • 这是现代 Web 开发中推荐的默认选择,因为它行为可预测且安全。
  • 使用 async

    • 当你的脚本是完全独立的,不依赖于 DOM 或其他脚本(例如,独立的广告代码、分析统计脚本)。
    • 当你希望脚本尽可能快地执行,并且不关心执行顺序。
    • 适用于那些对页面渲染没有直接影响的“辅助性”脚本。

总结defer 确保脚本在文档解析后、按顺序执行;async 则让脚本下载完就立刻执行,不保证顺序。在大多数需要操作 DOM 或有依赖关系的场景下,优先选择 defer

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值