使用 加载外部 JS 时,浏览器会阻塞 HTML 解析并立即执行;应将脚本置于 前、或加 defer(保证顺序)/async(无序),注意路径以 HTML 文件为基准,加载失败需手动监听 error 事件。

用 <script src></script> 加载外部 JS 文件,必须放在 HTML 解析流程里考虑顺序
浏览器遇到 <script src="xxx.js"></script> 时会暂停 HTML 解析,立即下载、编译并执行该 JS 文件。这意味着:如果脚本依赖 DOM 元素(比如想 document.getElementById 某个 <div>),而这个 <code><script></script> 又写在 里,大概率报 Cannot read property 'xxx' of null。
- 最稳妥的做法是把
<script src></script>放在闭合标签前 - 或者加
defer属性(仅适用于外部脚本):<script src="app.js" defer></script>,它会让脚本等 HTML 解析完再按顺序执行 -
async也行,但执行时机不可控,适合无依赖的分析统计类脚本
src 路径写错是 404 的主因,相对路径以 HTML 文件位置为基准
很多人以为 src="js/main.js" 是相对于当前 JS 文件位置,其实不是——它是相对于当前 HTML 文件的 URL。比如 HTML 在 /user/profile.html,那 src="js/main.js" 实际请求的是 /user/js/main.js,而不是 /js/main.js。
- 检查浏览器开发者工具 Network 面板,看请求的完整 URL 是否符合预期
- 用绝对路径更可控,比如
src="/static/js/utils.js"(开头带/表示从根目录开始) - 避免用
../嵌套太多层,容易在页面路由变化时失效
加载失败时没有默认提示,得靠 onerror 或 addEventListener('error') 捕获
<script src></script> 加载失败(如 404、跨域、网络中断)不会抛 JS 异常,也不会中断后续脚本,但目标文件里的逻辑完全不会运行,且静默失败。
- 可以绑定错误监听:
<script src="missing.js" onerror="console.error('JS load failed')"></script> - 更健壮的方式是用事件监听:
const s = document.createElement('script');<br>s.src = '/assets/logic.js';<br>s.addEventListener('error', () => console.warn('logic.js failed'));<br>document.head.appendChild(s); - 注意:内联
onerror只对当前<script></script>生效;动态创建的 script 才能灵活处理失败逻辑
多个 <script src></script> 的执行顺序受 defer/async 和位置共同影响
没加任何属性的 <script src></script> 是“阻塞 + 顺序执行”,但一旦混用 defer 和 async,行为就容易混乱。比如:
分析 Java Spring Boot 后端 Controller 代码,自动生成 Markdown 格式的接口文档。当用户说“生成 Java 接口文档”、“生成 API 文档”、“从 Spring 代码生成文档”时触发。
立即学习“Java免费学习笔记(深入)”;
-
<script src="a.js"></script>和<script src="b.js" defer></script>:a.js 立即执行,b.js 等 DOM 解析完再执行(且保证在 a.js 之后,因为 defer 脚本按出现顺序执行) -
<script src="c.js" async></script>和<script src="d.js" async></script>:谁先下载完谁先执行,顺序不确定 - 混合使用
defer和async时,async总是优先级更高,可能打断defer的顺序保证
实际项目中,如果模块有依赖关系(比如 jQuery → 插件),别图省事全加 async,老实用 defer 或手动控制加载链。

















