script 标签最稳妥位置是 之前;若放 中须加 defer 属性;内联脚本限10行内,复用逻辑必须抽为外部文件;type="module" 默认 defer、需带后缀路径、须 http 服务运行。

script 标签必须放在哪里才有效
浏览器解析 HTML 是从上到下顺序执行的,<script></script> 如果写在 开头但脚本里又去操作 document.getElementById('xxx'),大概率拿到 null——因为对应元素还没被解析出来。
常见错误现象:TypeError: Cannot read property 'xxx' of null 或脚本完全没反应。
- 最稳妥的位置是
之前(即底部) - 如果必须放
,加defer属性:<script src="app.js" defer></script>,它会等 DOM 解析完再执行 -
async适合纯工具类脚本(如统计代码),但不保证执行顺序,且可能在 DOM 尚未就绪时运行
内联 script 和外部 JS 文件怎么选
内联脚本(直接写在 <script>...</script> 里)适合几行初始化逻辑;外部文件(<script src="xxx.js"></script>)才是常规做法。
使用场景差异明显:
立即学习“Java免费学习笔记(深入)”;
- 页面级小交互(比如按钮点击弹个提示)可内联,但别超过 10 行,否则难维护
- 任何涉及函数封装、模块依赖、复用逻辑的,必须抽成
.js文件 - 外部文件支持浏览器缓存,重复访问更快;内联脚本每次都要重新下载
- 注意路径:如果
src是相对路径,以当前 HTML 文件位置为基准,不是以 JS 文件位置
type="module" 改变加载行为的坑
现代写法 <script type="module" src="main.js"></script> 默认开启严格模式、支持 import/export,但它有硬性限制。
容易踩的坑:
- 模块脚本自动启用
defer行为,但不支持async与defer同时写 - 模块内
import的路径必须带后缀(如./utils.js),不能省略.js - 模块脚本默认跨域策略更严,本地双击打开 HTML 会触发
CORS错误,必须走 HTTP 服务(如python3 -m http.server) - 传统脚本无法直接访问模块里的变量,反之亦然——它们是隔离的作用域
动态插入 script 标签要注意什么
用 JavaScript 动态创建并插入 <script></script>(比如按需加载 SDK),看似灵活,实则细节很多。
关键点:
- 创建后必须显式调用
appendChild()才会触发下载和执行,光document.createElement('script')不够 - 动态插入的脚本默认同步执行(类似没加
defer的传统脚本),可能阻塞渲染 - 如果依赖其他脚本,得手动控制顺序,比如监听前一个的
load事件再插入下一个 - 动态脚本中用
document.write会清空整个页面,绝对禁用
真正麻烦的从来不是“怎么加”,而是“什么时候加”和“加完能不能用”。DOM 就绪时机、模块作用域、路径解析规则、缓存策略——每个点都可能让 JS 看似加载了,却静默失败。










