前置知识点:
DOMContentLoaded在初始的HTML完全加载和解析完成之后触发,无需等待样式表、图像、子框架(iframe)的加载load在页面资源完全被加载解析完成之后触发
# sync script
浏览器在解析 HTML 时,如果遇到 script 标签,则会暂停解析,发起一个网络请求获取这个脚本,并解析执行这个脚本。
也就是说 script 的下载和执行会阻塞页面渲染,script 中的脚本只能访问已经解析的 DOM。
这里可以理解为普通的 script 是同步脚本,接下来要讲的是延迟脚本和异步脚本。
# defer script
当浏览器解析到一个延迟脚本时,浏览器会做如下处理:
- 如果是内敛脚本(即没有
src值),则会忽略defer,按照正常流程去解析执行这个脚本 - 否则浏览器会请求这个脚本,并且不足塞
HTML的解析 - 下载后,在
DOM解析完成后,DOMContentLoaded之前去执行它 - 如果存在多个带有 defer 的脚本,会按声明的顺序去执行
延迟脚本具有这几个特点:
- 不足塞
HTML解析 - 在
HTML解析完成后执行,执行后再触发DOMContentLoaded事件 - 多个
defer script之间按声明顺序执行 - 没有
src的defer script会忽略defer
# async script
当浏览器解析到一个异步脚本时,浏览器会做如下处理:
- 异步加载这个脚本,并且不足塞
HTML解析 - 下载完成则执行,执行可能在
DOMContentLoaded之前,也可能在之后,取决于脚本的下载完成的时间 - 多个
async脚本之间不会相互等待,即加载完则执行
异步脚本具有以下几个特点:
- 不足塞
HTML解析 - 下载完成后执行,没有其他限制
# dynamic script
动态创建的脚本默认具备异步脚本的特点,即 script.async 默认为 true,所以它默认也是异步加载,加载完就执行。
动态创建的 script,也可以设置 script.async = false,脚本将恢复至按创建的顺序去执行
# 使用
在实际使用中,defer 应该用在那些需要整个 DOM 并且依赖声明顺序的脚本上,async 应该用在那些独立的脚本上,比如广告、计数脚本,它们之间没有依赖关系。