Defer Script 和 Async Script
使用方式
首先来看一下以下三种不同的 js 引入方式:
<!-- 一、普通的 js 引入方式 -->
<script src="https://javascript.info/article/script-async-defer/long.js?speed=1"></script>
<!-- 二、含有 defer 属性的 js 引入方式 -->
<script defer src="https://javascript.info/article/script-async-defer/long.js?speed=1"></script>
<!-- 三、含有 async 属性的 js 引入方式 -->
<script async src="https://javascript.info/article/script-async-defer/long.js?speed=1"></script>
区别
先看一张图
根据上图我们大致可以理解 Script
、Defer Script
、Async Script
三者的区别:
- Script 根据在 HTML 中的声明顺序依次下载并执行。一旦遇到 script 标签则立即中断 DOM 的解析,转而下载和运行该 Script
- Defer Script 则是根据在 HTML 中的声明顺序在后台进行下载,直至 DOM 解析完毕后(DOMContentLoaded 执行之前)再运行该 script。遇到 defer script 不会中断 DOM 的解析。
- Async Script 和 Defer Script 有一个共同点:并行下载,它们都不会阻塞页面。但是不同于 Defer Script 的是:Async Script 在下载完毕后会中断 DOM 的解析(除非此时 DOM 已经渲染完毕),因此它有可能在 DOMContentLoaded 之前执行, 也有可能在 DOMContentLoaded 之后执行,这取决于 Async Script 的下载和 DOM 解析的过程谁先完成。(Async Script 可以用作网站访问分析,因此它们不依赖于其他任何的 script 和 DOM 元素,同时其他内容也不依赖于它们)
- Defer Script 是声明优先,它们根据其在 HTML 中声明的顺序有序执行。而 Async Script 则是加载优先,谁先下载完毕谁就先去执行。
补充内容
- DOM 解析完毕并不意味着可以立即在浏览器看到展示的内容,而是可以通过 document 操作页面元素而已
- Defer Script 和 Async Script 只对含有 src 属性的外部脚本生效
- 如果在一个 script 上同时设置 async 和 defer 属性,那么 async 属性则具有比 defer 更高的优先级,仅当浏览不支持 Async Script 但支持 Defer Script 时 defer 属性才生效,否则两者都不生效。
- 如果你使用的是 Defer Script 或 Async Script,那么用户将在
脚本加载完成之前
先看到页面。在这种情况下,某些图形组件可能尚未初始化完成。因此,请记得添加一个 "正在加载" 的提示,并禁用那些尚不可用的按钮。以让用户可以清楚地看到,他现在可以在页面上做什么,以及还有什么是正在准备中的。
Dynamic Script
我们称下面这类 script 为 Dynamic Script
const script = document.createElement('script');
script.src = 'test.js';
document.body.appendChild(script);
console.log(script.async); // true
console.log(script.defer); // false
通过控制台的打印结果可知:Dynamic Script 等同于 Async Script,当然我们可以通过在其加载到页面之前修改相应的属性值来改变其执行顺序。