async让脚本异步下载且下载完成立即执行,可能中断html解析、dom未就绪;defer则等html解析完、domcontentloaded前按序执行,保证dom可用和执行顺序。

async 属性到底让脚本怎么“异步”
async 不是“后台下载完再执行”,而是“下载不阻塞 HTML 解析,但一旦下载完成就立即中断当前 HTML 解析、执行脚本”。这意味着它和 DOM 构建是竞争关系——async 脚本执行时,document 很可能还没解析完,DOMContentLoaded 事件还没触发。
适用场景很明确:纯工具类脚本(如统计代码、CDN 加载的第三方 SDK),不依赖 DOM,也不被其他脚本依赖。
-
async只对**外部脚本**生效(即带src的<script></script>),内联脚本写async会被忽略 - 多个
async脚本**不保证执行顺序**,哪怕它们在 HTML 中前后排列,谁先下完谁先执行 - 它会跳过
defer和普通同步脚本的排队机制,属于“插队型异步”
async 和 defer 的关键区别在哪
两者都让下载不阻塞 HTML 解析,但执行时机完全不同:async 是“下载完立刻执行”,defer 是“等 HTML 解析完、DOM 构建完毕后,按书写顺序执行”。
典型误用:把初始化 DOM 的脚本(比如 document.querySelector 操作)用 async 加载,结果报错 Cannot read property 'querySelector' of null 或直接找不到元素。
如果你了解HTML,CSS和JavaScript,您已经拥有所需的工具开发Android应用程序。本动手本书展示了如何使用这些开源web标准设计和建造,可适应任何Android设备的应用程序 - 无需使用Java。您将学习如何创建一个在您选择的平台的Android友好的网络应用程序,然后转换与自由PhoneGap框架到一个原生的Android应用程序。了解为什么设备无关的移动应用是未来的潮流,并开始构建应用程序,提供更
- 需要操作 DOM?优先选
defer,或把逻辑包进DOMContentLoaded事件监听里 - 脚本之间有依赖(如 jQuery + 插件)?
async会破坏顺序,必须改用defer或模块化方案(type="module") -
async脚本中调用console.log(document.body),大概率输出null
实际写法与常见错误
正确写法很简单:<script async src="analytics.js"></script>。但容易出问题的是路径、加载失败处理和重复加载。
- 不要给
async脚本加onload回调后就以为“稳了”——如果脚本 404,onload不触发,onerror才会,得主动监听 - CDN 地址失效或网络异常时,
async脚本静默失败,页面可能功能缺失但无提示 - 避免在同一个页面多次引入相同
src的async脚本,浏览器不会去重,可能重复执行(尤其动态插入时) - Webpack/Vite 打包产物若配置了
scriptType: "module",async对type="module"无效,此时应改用defer
什么时候不该用 async
当脚本需要访问完整 DOM、依赖其他脚本、或本身是应用主入口时,async 基本就是埋雷。
- Vue/React 应用入口文件(如
main.js)——必须等 DOM 就绪,且常依赖其他模块,用defer或type="module"更稳妥 - 含
document.write()的旧脚本(虽已淘汰,但老系统还存在)——async下它会清空整个页面 - 通过
document.currentScript获取自身路径做资源定位的脚本——async下该 API 可能返回null - 服务端渲染(SSR)后需 hydration 的前端框架——hydration 必须等 DOM 树完整,
async会破坏时机
async 的“快”是有代价的:放弃可控性换来的并行下载。真正要优化首屏,往往得结合 code-splitting、预加载(<link rel="preload">)和资源优先级调度,而不是单靠一个属性。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










