在HTML中会遇到一下三类script
<script src=""></script>
<script src="" async></script>
<script src="" defer></script>
那么这三类有什么区别呢?
script
浏览器在解析HTML代码的时候,如果遇到一个没有任何属性的script标签,就会暂停解析HTML,先发送网络请求获取该js脚本的代码并解析,然后让js引擎执行该代码,当js代码执行完毕后恢复解析。整个过程如下图所示:
可以看到,script阻塞了浏览器对HTML的解析,如果获取js脚本的网络请求迟迟得不到响应后者js脚本执行时间过长,都会导致白屏用户看不到内容。
async script
async表示异步,但浏览器遇到带有async属性的script时,请求该脚本的网络请求是异步的,不会阻塞浏览器解析HTML,一旦网络请求回来之后,分一下两种情况:
-此时HTML还没有解析完,浏览器会暂停解析HTML,先让js引擎执行代码,执行完毕后再解析HTML;
-此时HTML代码解析完成,直接执行js代码;
所以async是不可控的,执行时间不确定,如果在异步js脚本中获取某个DOM元素,有可能获取到也有可能获取不到而且如果存在多个async的时候,他们之间的执行顺序也是不确定的,完全依赖网络传输结果,谁先到执行谁。
defer script
defer表示延迟,当浏览器遇到带有defer属性的script的时候,获取该脚本的网络请求也是异步的,不会阻塞浏览器解析HTML,一旦网络请求回来之后,如果此时HTML代码还没有解析完,浏览器不会暂停解析HTML代码并执行js代码,而是等待HTML解析完毕以后再执行js代码,如图:
如果存在多个defer script标签,浏览器会保证他们按照在HTML中出现的顺序执行,不会破坏js脚本之间的依赖关系。
总结:
script 标签 JS 执行顺序 是否阻塞解析 HTML
<script> 在 HTML 中的顺序 阻塞
<script async> 网络请求返回顺序 可能阻塞,也可能不阻塞
<script defer> 在 HTML 中的顺序 不阻塞