前言
我们在写html的时候基本会碰到以下三种script
标签,这三种script
有什么区别你知道吗?
<script src='xxx'></script>
<script src='xxx' async></script>
<script src='xxx' defer></script>
script
浏览器在解析HTML
的时候,如果遇到一个没有任何属性的script
标签,就会暂停解析,先发送网络请求获取该JS
的代码内容,然后让JS
执行该代码,当代码执行完毕后再接着解析HTML
。
也就是说script
阻塞了浏览器对HTML
的解析,如果获取JS
的网络请求没有得到回应,或者JS
执行时间过长,都会导致页面的长时间白屏,让用户看不到页面。
async script
async
表示异步,当浏览器遇到带有async
属性的script
时,请求该脚本的网络请求是异步的,不会阻塞浏览器解析HTML
,一旦网络请求回来之后,如果此时HTML
还没有解析完,浏览器会暂停解析,先让JS
先执行代码,执行完毕后再进行解析HTML
,当然,如果在JS
请求回来之前,HTML
已经解析完毕了,那就会立即执行JS
代码,
所以async
是不可控的,因为JS
的执行时间不确定,所以如果想要在一个异步JS
脚本中获取某个DOM
元素,有可能获取到也有可能获取不到。而且如果存在多个 async 的时候,它们之间的执行顺序也不确定,完全依赖于网络传输结果,谁先到执行谁。 这就会导致如果我们导入的第二个JS
依靠第一个JS
执行,那么第二个JS
的执行就有可能出现问题
defer script
defer
表示延迟,当浏览器遇到带有defer
属性的script
时,获取该脚本的网络请求也是异步的,不会阻塞浏览器解析 HTML
,一旦网络请求回来之后,如果此时HTML
还没有解析完,浏览器不会暂停解析并执行JS
代码,而是等待HTML
解析完毕再执行JS
代码。
并且如果存在多个defer script
标签,浏览器会保证它们按照在HTML
中出现的顺序执行,不会破坏JS
脚本之间的依赖关系。
总结
-
<script src='xxx'></script>
:常规的script
标签会阻塞浏览器的解析,直到脚本加载并执行完毕。 -
<script src='xxx' async></script>
:带有async
属性的script
标签会异步加载脚本,加载完成后会立即执行,可能阻塞,也可能不阻塞文档解析,执行时机不确定。 -
<script src='xxx' defer></script>
:带有defer
属性的script
标签也是异步加载脚本,但会在文档解析完成后、DOMContentLoaded
事件触发前执行,多个defer script
会按照顺序执行,并且不会破坏脚本之间的依赖关系。