async脚本无执行顺序保证,依赖脚本可能未定义导致referenceerror;defer能按html顺序执行但需全为外部文件且声明顺序正确;内联脚本始终同步执行,易因dom未就绪而失败。

async 脚本之间**没有执行顺序保证**,哪怕 HTML 里 <script async src="a.js"></script> 写在 <script async src="b.js"></script> 前面,只要 b.js 下载更快,它就会先执行。
多个 async 脚本为什么总报 ReferenceError?
典型错误如 utils is not defined 或 initApp is not a function,根本原因是脚本 A 依赖脚本 B 导出的变量或函数,但 A 先执行了——浏览器根本不关心你写的顺序,只看谁先下载完。
-
async只对带src的外部脚本生效,内联脚本加async属性会被忽略 - 所有
async脚本都是独立宏任务,彼此不排队、不等待、不协调 - 一旦脚本里出现
import、require、utils.init()、document.querySelector这类调用,就说明它不独立,不该用async
defer 真能解决顺序问题吗?
能,但有硬前提:所有脚本必须是外部文件,且必须按依赖顺序在 HTML 中声明。比如 utils.js 必须写在 main.js 前面,否则 main.js 执行时 utils 还没定义。
- 多个
defer脚本严格按 HTML 中出现顺序执行,哪怕main.js下载慢于utils.js,也等它一起等到 DOM 解析完再顺序跑 -
defer不适用于需要尽早运行的脚本(比如首屏性能埋点),它一定会等到DOMContentLoaded前才执行 - 如果某个脚本要操作
里刚解析出来的元素,而该元素在<script defer></script>后面,没问题;但如果元素在<script defer></script>前面,且脚本没加defer,就可能拿不到
混用 async、defer 和内联脚本最常踩的坑
现实项目里经常这样写:async 加统计脚本、defer 加业务逻辑、底部还留一个 <script>init();</script>。最容易被忽略的是:内联脚本永远同步执行,它会卡在它出现的位置,不管前后有没有 async 或 defer。
- 内联脚本访问
document.getElementById可能返回null,因为它执行时 DOM 可能还没建完 -
async脚本执行时会中断 HTML 解析,此时访问document.body是安全的,但访问具体元素仍需确认存在 - 浏览器不会帮你 resolve 依赖链,它只忠实地按规范执行加载策略——依赖关系必须显式声明,不能靠“我写得早它就该先加载”这种直觉
真正复杂的点不在属性本身,而在脚本之间的依赖是否被显式声明;async 和 defer 都不解决依赖,只控制加载与执行时机。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











