async脚本下载完立即执行,可能早于DOM就绪;defer脚本等HTML解析完、DOMContentLoaded前按序执行。async不保序,defer保序;async适合独立统计脚本,defer适合依赖DOM或有先后依赖的业务逻辑。

async 和 defer 都能让外部 JavaScript 脚本异步加载,避免阻塞 HTML 解析,但它们的执行时机和顺序规则完全不同。选错属性可能导致脚本执行失败或逻辑错乱,尤其在依赖 DOM 或存在先后依赖时。
执行时机不同
async 脚本一旦下载完成就立刻执行,不管 HTML 是否解析完——可能在 DOM 构建中途 就运行,此时 document 可能还不完整;defer 脚本则严格等到整个 HTML 解析完毕、DOMContentLoaded 触发前 才执行,此时 DOM 已就绪。
- async:下载完 → 立即执行(哪怕 <body> 还没读到)
- defer:下载完 → 暂存 → HTML 全部解析完 → 按序执行
多个脚本的执行顺序不同
如果页面引入多个外部脚本,顺序控制很关键:
- 多个 async:谁先下载完谁先执行,**完全不保证声明顺序**,比如 script2.js 比 script1.js 快,就会先运行
- 多个 defer:始终按它们在 HTML 中出现的**书写顺序依次执行**,适合库文件 + 业务代码这种依赖链
适用场景有明确分工
不是“哪个更快就用哪个”,而是看脚本是否需要 DOM、是否相互依赖:
立即学习“Java免费学习笔记(深入)”;
- 用 async:统计代码(如 GA)、广告脚本、埋点 SDK——独立运行、无需操作页面元素
- 用 defer:初始化逻辑、表单验证、轮播组件——要访问 DOM,或依赖前面加载的工具库(如先加载 lodash,再加载业务模块)
- 不用 async/defer:内联脚本(
<script>...</script>)或必须同步执行的配置脚本
一些实际注意事项
这些细节容易被忽略,但会影响行为一致性:
- 两者都只对外部脚本(
src属性存在时)有效,内联脚本加了也没用 - 如果同时写
async defer,浏览器会优先按 async 处理,defer 被忽略 - defer 脚本执行完才会触发
DOMContentLoaded;async 脚本执行不参与该事件的等待队列 - 现代实践中,多数业务 JS 推荐用 defer;第三方无依赖资源(如 analytics.js)用 async 更合理


















