脚本加载对window.load事件有什么影响?动态加载脚本时window.load何时触发?
window.load 触发时机与脚本加载关联规则
首先明确HTML规范中定义的window.load触发前提:等待页面所有初始解析阶段识别的静态资源加载完成,包括静态声明的图片、样式表、字体、脚本等。
不同静态script标签下的触发规则
- 无属性的同步script:HTML解析到标签时直接阻塞解析,同步加载并执行脚本,执行完成后才继续解析后续DOM。这类脚本一定会在window.load触发前执行完成,window.load会等待其执行结束。
- 带
defer属性的script:脚本加载和HTML解析并行,不会阻塞解析,所有defer脚本会按标签声明顺序在DOMContentLoaded事件触发前、DOM解析完成后执行,window.load会等待所有defer脚本执行完成后再触发。 - 带
async属性的script:脚本加载和HTML解析并行,加载完成后立即中断解析执行脚本,执行顺序不按标签声明顺序。如果async脚本在HTML完成初始解析前就加载完成,window.load会等待其执行结束;如果async脚本加载完成的时机晚于HTML初始解析完成、且其他所有静态资源都已加载完成,window.load不会等这个async脚本,会直接触发。你观察到的window.load等待async脚本的情况,是刚好这些async脚本加载完成的时机在静态资源加载完成前。
动态加载脚本的判定规则
浏览器判断window.load是否需要等待资源的核心依据是:资源是否在「当前文档的解析器关闭」前被加入到资源加载队列。
- 所有在静态HTML解析阶段(也就是浏览器原生解析初始HTML文本、还没触发DOMContentLoaded的阶段)同步执行的脚本里,动态创建的
<script>标签,如果是在初始解析的同步执行逻辑里插入到DOM中的,会被加入浏览器的资源加载队列,window.load会等待这些动态脚本加载执行完成。 - 如果动态脚本是在异步回调中创建插入的(比如setTimeout回调、某个异步请求的回调、其他async/defer脚本的异步逻辑里插入),或者是在DOMContentLoaded触发后才插入的,这些脚本不会被计入window.load的等待队列,window.load不会等它们加载完成就会触发。
举个实际的示例:
<!-- 静态声明的同步脚本 --> <script> // 这段脚本在HTML初始解析阶段同步执行 const script1 = document.createElement('script'); script1.src = 'test1.js'; document.body.appendChild(script1); // 这个动态script会被window.load等待 setTimeout(() => { const script2 = document.createElement('script'); script2.src = 'test2.js'; document.body.appendChild(script2); // 这个动态script在异步回调里插入,window.load不会等它 }, 0) </script>
内容的提问来源于stack exchange,提问作者d_bhatnagar
相关产品推荐
相关产品推荐

