script标签中的async和defer属性到底是干什么的?

868 阅读2分钟

“我正在参加「兔了个兔」创意投稿大赛,详情请看:「兔了个兔」创意投稿大赛

前言

日常开发中,我们使用的script标签基本上恒定在三种

  • 带defer的
  • 带async的
  • 什么都没带的

如下

image.png

这三种主要是决定浏览器对于js解析和执行是否阻塞html解析

我们看看详细分析。

< script src="" > (不带async和defer的)

图片注释:
绿色(html解析过程)
灰色(html暂停解析过程)
紫色(script下载过程)
红色(script执行过程)

不带async和defer的script标签会阻塞html的解析 image.png (原图地址:async vs defer attributes - Growing with the Web

由图得知:在script标签同时不具备defer和async的情况下。script标签的下载和执行都会阻塞html的渲染。

< script src="" async> (带async不带defer的)

只有async的script标签可能会阻塞html的解析

image.png (原图地址:async vs defer attributes - Growing with the Web

由图得知:在script标签在有async的情况下。script标签的下载是异步的,不会阻塞html的渲染,但是script的执行依然会阻塞html的解析。

但这里有一个问题:为什么上面说:只有async的script标签可能会阻塞html的解析,为什么是可能会而不是一定会?有没有可能不会阻塞。

有。

1670229160758.jpg.png (图片地址:自己P的,没有来源地址)

比如如上情况,我们加载script完毕的时候,html已经解析完成了。那么这个时候再去执行script就不会阻塞html解析。

< script src="" defer> (带defer不带async的)

只有defer的script标签不会阻塞html的解析

image.png (原图地址:async vs defer attributes - Growing with the Web

如图:仅仅携带defer属性的script标签加载是异步的,所以加载不会阻塞html解析。加载完成之后也不会马上执行,而是等待html解析完毕之后再执行,所以执行也不会阻塞html的渲染。

还有几个小问题

如果script标签同时具备async和defer会有什么效果?

在script同时具备async和defer的情况下。不论先后顺序,效果和async是一样的。

如果有多个携带defer属性的script标签,他们的执行顺序会乱吗?

不会。如果有多个携带defer属性的script标签。他们的执行顺序是根据我们编码的顺序去执行的,所以不用担心他们之间的依赖关系。

但是以上都是针对script放在head的时候出现的情况。写过jq的小伙伴都应该会一种操作,就是把script标签放到body之后去写,这样,即便不写async和defer也可防止script标签阻塞html解析。