async、defer 的区别是什么?

前言

在了解 <script> 标签上 asyncdefer 属性的作用之前,让我们先来回顾一下 JavaScript 的加载时间线。

JavaScript 在网页加载过程中对页面的性能以及用户体验有着至关重要的影响,了解 JavaScript 的加载时间线,有助于更好的开发优化网页。

一、Web 页面解析初始阶段

浏览器在解析的过程中,自上而下依次读取 HTML 文档,创建 Document 对象,渲染元素节点到文档中。此阶段 document.readyState = 'loading'

二、外部样式资源加载

当浏览器遇到一个<link>标签且 href 指向一个外部的 stylesheet 文件时,浏览器会创建线程记载,并继续向下解析文档。

三、同步的外部脚本加载

当浏览器遇到一个<script>标签且其 src 属性指向一个外部样式表文件时,并且没有设置 asyncdefer 属性,浏览器会暂停 HTML 的解析,去下载并立即执行这个外部脚本。

四、异步的外部脚本加载

当浏览器遇到一个<script>标签且其 src 属性指向一个外部 JavaScript 文件时,并且设置有 asyncdefer 属性,浏览器会创建线程加载,并继续向下解析文档。

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 脚本会按照文档的顺序依次执行,顺序可控。

最后

感谢你的阅读~

如果你有任何的疑问欢迎您在后台私信,我们一同探讨学习!

如果觉得这篇文章对你有所帮助,点赞、在看是最大的支持!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值