defer 和 async 是 <script> 标签用于控制 JavaScript 脚本加载与执行时机的重要属性,它们的核心区别在于 加载过程 和 执行时机,以下从三个维度详细解析:
1. 加载过程对比
-
普通脚本(无属性)
浏览器解析 HTML 遇到<script>标签时,立即暂停解析,发起网络请求加载 JS 文件,加载完成后执行代码,执行完毕才继续解析 HTML。
关键影响:阻塞页面渲染,导致白屏时间延长。 -
defer 脚本
浏览器解析 HTML 遇到<script defer>标签时,并行加载 JS 文件(不阻塞 HTML 解析),但会将脚本执行推迟到 HTML 解析完成后(DOMContentLoaded事件触发前)。
关键特性:- 多个
defer脚本按 HTML 中的顺序执行(保证依赖关系)。 - 适用于需要操作 DOM 或依赖其他脚本的代码(如 jQuery 插件)。
- 多个
-
async 脚本
浏览器解析 HTML 遇到<script async>标签时,并行加载 JS 文件(不阻塞解析),但文件加载完成后 立即执行,执行时会暂停 HTML 解析。
关键特性:- 多个
async脚本的执行顺序 不确定(取决于加载完成时间)。 - 适用于独立功能(如广告、统计脚本),不依赖 DOM 或其他脚本。
- 多个
2. 执行时机对比
| 属性 | 是否阻塞 HTML 解析 | 执行时机 | 执行顺序 |
|---|---|---|---|
| 无(默认) | ✅ 阻塞 | 加载完成后立即执行 | 按 HTML 顺序 |
defer | ❌ 不阻塞 | HTML 解析完成后(按序) | 按 HTML 顺序 |
async | ❌ 不阻塞 | 加载完成后立即执行 | 不确定(加载快的先执行) |
3. 典型应用场景
-
defer 的最佳场景
- 引入依赖 DOM 的库(如 Vue/React 等框架)。
- 执行需要操作完整 DOM 树的代码(如初始化表单验证)。
- 示例:
html
预览
<script defer src="main.js"></script>
-
async 的最佳场景
- 加载独立功能的第三方脚本(如 Google Analytics、广告 SDK)。
- 示例:
html
预览
<script async src="https://analytics.google.com/analytics.js"></script>
4. 兼容性与注意事项
-
兼容性
defer:IE9+、现代浏览器全支持。async:IE10+、现代浏览器全支持。- 如需兼容 IE9-,需使用传统方案(如将
<script>放在<body>底部)。
-
性能优化建议
- 核心业务脚本(如主应用逻辑)使用
defer,确保按序执行且不阻塞渲染。 - 非关键脚本(如埋点、评论框)使用
async,减少对主流程的影响。 - 避免在
async脚本中操作 DOM(可能因 DOM 未就绪导致错误)。
- 核心业务脚本(如主应用逻辑)使用
总结
- defer:延迟执行,顺序保证,适合需要操作 DOM 且有依赖关系的脚本。
- async:异步加载,执行时机不定,适合独立功能、不依赖其他资源的脚本。
选择时需根据脚本的依赖关系、对 DOM 的操作需求以及性能优化目标综合判断。
1698

被折叠的 条评论
为什么被折叠?



