HTML-script标签中的defer和async的区别

201 阅读2分钟

主要决定了脚本加载的方式

一、核心区别对比表

特性普通scriptasyncdefer
执行顺序按书写顺序执行谁先加载完谁先执行(无序)按书写顺序执行(有序)
执行时机立即执行,阻塞渲染加载完立即执行,可能阻塞渲染DOM解析完成后执行,不阻塞渲染
适用场景无依赖的独立脚本统计代码、广告脚本有依赖关系的脚本(如jQuery插件)
DOM访问可能访问不完整DOM可能访问不完整DOM可以访问完整DOM

二、执行时序图解析(重点!)

普通script:
HTML解析 -> 遇到script -> 暂停解析 -> 下载执行 -> 继续解析

async:
HTML解析 -> 遇到script -> 并行下载 -> 下载完成立即执行 -> 继续解析

defer:
HTML解析 -> 遇到script -> 并行下载 -> HTML解析完成 -> 按顺序执行

三、代码示例验证

<!DOCTYPE html>
<html>
<head>
  <!-- 异步加载 -->
  <script async src="async1.js"></script>
  <script async src="async2.js"></script>
  
  <!-- 延迟执行 -->
  <script defer src="defer1.js"></script>
  <script defer src="defer2.js"></script>
</head>
<body>
  <div>页面内容...</div>
</body>
</html>

假设加载速度:

  • async2.js 比 async1.js 先加载完
  • defer1.js 和 defer2.js 按顺序加载

执行顺序结果

  1. async2.js 先执行(谁快谁先)
  2. async1.js 后执行
  3. defer1.js
  4. defer2.js(保持书写顺序)

四、高频面试题精讲

1. 如果同时使用async和defer会怎样?

<script async defer src="script.js"></script>

现代浏览器会优先采用async行为(当作async处理)

2. 怎么选择用async还是defer?

  • 需要尽早执行且不依赖DOM → async(如网站统计代码)
  • 有依赖关系或需要操作DOM → defer(如jQuery+Bootstrap)

3. 对DOMContentLoaded事件的影响

document.addEventListener('DOMContentLoaded', () => {
  console.log('DOM解析完成');
});
  • async脚本可能阻塞DOMContentLoaded
  • defer脚本在DOMContentLoaded之前执行

五、记忆口诀

"异步async谁快谁先上,延迟defer顺序不能乱
普通脚本阻塞要小心,统计广告适合用异步"

配合对比表格和时序图理解,面试时如果被问到,可以这样回答:
"async和defer都能实现异步加载,但async是无序执行适合独立脚本,defer保持顺序适合依赖型脚本。实际开发中需要操作DOM的脚本建议用defer,像Google Analytics这种统计代码适合用async。"