前言
在了解 <script>
标签上 async
和 defer
属性的作用之前,让我们先来回顾一下 JavaScript
的加载时间线。
JavaScript
在网页加载过程中对页面的性能以及用户体验有着至关重要的影响,了解 JavaScript
的加载时间线,有助于更好的开发优化网页。
一、Web 页面解析初始阶段
浏览器在解析的过程中,自上而下依次读取 HTML
文档,创建 Document
对象,渲染元素节点到文档中。此阶段 document.readyState = 'loading'
。
二、外部样式资源加载
当浏览器遇到一个<link>
标签且 href
指向一个外部的 stylesheet
文件时,浏览器会创建线程记载,并继续向下解析文档。
三、同步的外部脚本加载
当浏览器遇到一个<script>
标签且其 src
属性指向一个外部样式表文件时,并且没有设置 async
或 defer
属性,浏览器会暂停 HTML
的解析,去下载并立即执行这个外部脚本。
四、异步的外部脚本加载
当浏览器遇到一个<script>
标签且其 src 属性指向一个外部 JavaScript
文件时,并且设置有 async
或 defer
属性,浏览器会创建线程加载,并继续向下解析文档。
async
脚本加载完成后会立即执行,此阶段禁止使用 document.write()
。
五、文件资源加载
当浏览器遇到 <img>
、<video>
等资源标签时,浏览器会先正常解析 DOM
结构,然后在异步的加载 src
资源,并继续向下解析文档。
六、文档解析完成
此阶段 document.readyState = 'interactive'
。
七、defer 脚本执行
文档解析完成后,浏览器会按照文档的脚本顺序依次执行 defer
的脚本。
与 async
一样,此阶段禁止使用 document.write()
。
八、事件驱动阶段
此阶段 document
对象触发 DOMContentLoaded
事件,也标志着程序执行从同步脚本执行阶段,转化为事件驱动阶段。
九、资源脚本加载并执行完成
当所有的 async
的脚本加载执行完成、<img>
、<video>
等资源加载完成后,window 对象触发 load
事件。
此阶段 document.readyState = 'complete'
,表示页面的所有资源都已经加载完成,页面处于完全可用的状态。
十、异步事件处理阶段
此阶段,浏览器以异步响应方式处理用户输入、网络事件等。
async、defer 的区别
当遇到了一个非常耗时的脚本,在该脚本执行结束前,页面被阻塞,用户都不能看到页面内容;
<script>for (let i = 0; i < 1000000000; i++) {// 一个非常耗时的循环}
</script>
<p>content1</p>
<p>content2</p>
当然因为浏览器是自上而下依次依次执行的,我们可以把脚本放在页面底部,也不会阻塞页面展示内容。
<p>content1</p>
<p>content2</p>
<script>for (let i = 0; i < 1000000000; i++) {// 一个非常耗时的循环}
</script>
初次之外我们也可以使用 <script>
中 async、defer
属性,他们都可以进行创建线程加载,不会阻塞页面展示内容。
<script async>for (let i = 0; i < 1000000000; i++) {// 一个非常耗时的循环}
</script>
<p>content1</p>
<p>content2</p>
虽然 async、defer
都可以异步加载,但是他们在行为上有着不同点。
<script async src="./script/a.js"></script>
<script async src="./script/b.js"></script>
当 <script>
设置了 async
属性,其他脚本不会等待 async
脚本加载完成,同样,async
脚本也不会等待其他脚本。
也就是谁先加载完成谁先执行,导致我们不知道 a.js
先执行还是 b.js
先执行,这种方式适合相互之间独立的脚本。
<script defer src="./script/a.js"></script>
<script defer src="./script/b.js"></script>
而 <script>
设置了 defer
属性,那么脚本将按照顺序依次执行,a.js
执行完成后执行 b.js
,这种方式适合脚本被依赖的情况下。
总结
<script>
中 async、defer
属性都是用来异步加载脚本,不会阻塞页面渲染。
async
脚本是先加载完成先执行,无法保证执行顺序。
defer
脚本会按照文档的顺序依次执行,顺序可控。
最后
感谢你的阅读~
如果你有任何的疑问欢迎您在后台私信,我们一同探讨学习!
如果觉得这篇文章对你有所帮助,点赞、在看是最大的支持!