HTML中JS执行时机由<script>位置决定:放</body>前最稳妥;放<head>需加defer(保序延迟)或async(独立脚本,时机不可控);src路径需注意协议、缓存与相对/绝对写法;禁用内联onclick,改用addEventListener;ES模块需type="module"且路径合规,自动defer和严格模式。

直接写 <script> 标签,但位置决定执行时机
HTML 里加 JS 最快的方式就是把代码塞进 <script> 标签里。但它放哪儿,JS 就啥时候跑——这点不注意,document.getElementById 找不到元素、addEventListener 绑不上,全是因为脚本执行太早。
常见错误现象:Uncaught TypeError: Cannot set properties of null,基本就是 DOM 还没加载完,JS 就急着操作节点了。
- 想确保 DOM 就绪:把
<script>放在</body>前面(最稳妥) - 必须放
<head>?加defer属性,它会等 HTML 解析完再执行,且保持顺序 - 用
async?只适合完全独立的脚本(比如统计代码),它下载时不阻塞,但执行时机不可控,可能 DOM 还没出来就跑了
src 引入外部 JS 文件,路径和加载方式要分清
项目一复杂,JS 肯定得拆文件。用 src 属性引入时,路径写错、协议混用、缓存干扰,三个坑占了八成问题。
使用场景:本地开发常用相对路径,上线后常配 CDN 或带版本号的 URL,避免浏览器缓存旧逻辑。
立即学习“前端免费学习笔记(深入)”;
- 路径错误典型表现:
net::ERR_ABORTED或404,检查浏览器开发者工具 Network 标签页里请求的完整 URL 是否拼错 - 本地双击打开 HTML?
file://协议下,某些浏览器会拦截src加载(尤其跨目录),改用本地服务器(如python3 -m http.server) - 想强制更新?在 URL 后加查询参数,比如
main.js?v=1.0.2,但别用时间戳,影响缓存利用
内联 onclick 看似简单,实际埋雷最多
写 <button onclick="doSomething()"> 是能跑,但很快就会卡在作用域、this 指向、HTML 实体转义上。
性能影响不大,但可维护性断崖式下跌,多人协作时没人敢动这段 HTML。
-
onclick里的代码运行在全局作用域,闭包变量、模块导入的函数都访问不到 - 字符串里写 JS,引号嵌套极易出错,
onclick="say('he said "ok"')"这种必须手动转义,容易漏 - 绑定多个事件?内联只能写一个
onclick,没法像addEventListener那样叠加 - 真要快速调试?临时用可以,上线前务必迁移到外部文件 +
addEventListener
ES 模块(type="module")不是“高级功能”,是现代项目的默认起点
不用 type="module",你就没法用 import/export,也没法用顶层 await,更没法享受自动的严格模式和作用域隔离。
兼容性现在其实很稳:Chrome 61+、Firefox 60+、Safari 11+、Edge 16+ 都支持,除非还要兼容 IE 或极老安卓 WebView。
- 必须用
src,不能写内联模块代码(<script type="module">console.log(1)</script>会报错) - 模块路径必须是完整 URL 或以
/、./、../开头,script.js这种裸名会被当成普通脚本处理 - 模块默认延迟执行(类似
defer),且自动启用严格模式,this在顶层是undefined


















