脚本执行时机由加载方式(sync/defer/async)和浏览器解析流程共同决定,DOMContentLoaded 表示 DOM 构建完成且同步与 defer 脚本已执行,load 则表示所有资源加载完毕;推荐用事件监听确保时机准确。

脚本执行时机不是由 DOMContentLoaded 或 load 事件“决定”的,而是由脚本的加载方式(sync、defer、async)和浏览器解析流程共同确定的;这两个事件只是反映 DOM 构建或资源加载完成的信号,可用来安排后续逻辑,但不控制脚本本身何时运行。
脚本加载方式直接影响执行顺序
浏览器按以下规则处理脚本,进而影响它与两个事件的关系:
-
同步脚本(默认):阻塞 HTML 解析,必须等其下载并执行完,DOM 构建才会继续;因此
DOMContentLoaded一定在其后触发,且该脚本自身必然在DOMContentLoaded前执行。 -
defer脚本:不阻塞解析,但保证按书写顺序在 DOM 构建完成后、DOMContentLoaded触发前执行;适合依赖完整 DOM 的初始化代码。 -
async脚本:独立异步加载,下载完立即执行,可能早于或晚于DOMContentLoaded;不能保证执行顺序,也不适合操作尚未就绪的 DOM。
DOMContentLoaded 是 DOM 就绪的可靠信号
该事件表示 HTML 已解析完毕、DOM 树已构建完成,且所有同步脚本和 defer 脚本均已执行。此时可安全进行:
- 查询和操作 DOM 元素(如
document.querySelector) - 绑定事件监听器(如点击、输入)
- 初始化 UI 组件(只要不依赖图片尺寸、CSS 渲染结果)
注意:若 CSS 文件未加载完,某些样式相关属性(如 offsetHeight)可能仍为 0,这不是事件时机问题,而是渲染管线尚未完成。
立即学习“Java免费学习笔记(深入)”;
load 事件代表全部资源就绪
该事件在页面所有资源(图片、字体、iframe、CSS、JS 等)都加载并解析完毕后触发。适用于需要确保视觉内容完全可用的场景:
- 读取图片真实尺寸(
img.naturalWidth) - 启动基于 Canvas 的绘图(需图像资源加载完成)
- 初始化依赖第三方 iframe 内容的功能(如嵌入式评论)
- 统计首屏加载完成时间(含图片)
实际开发中推荐的写法
避免依赖脚本执行顺序,统一用事件监听确保时机准确:
- DOM 操作 → 监听
DOMContentLoaded,或使用defer脚本 - 资源感知操作 → 监听
window.addEventListener('load', ...) - 不要在
DOMContentLoaded回调里访问未加载图片的布局属性;如需,改用img.onload单独监听 - 现代项目中,对懒加载、可见性判断等需求,优先考虑
IntersectionObserver或visibilitychange,而非硬等load


















