一般来说为了防止页面白屏,script标签会放到body标签的最后面也就是</body>之前。如果把script标签放在head标签里而且没有 defer 或 async,浏览器会立即加载并执行指定的脚本,“立即”指的是在渲染该script标签之下的文档元素之前,也就是说不等待后续载入的文档元素,读到就加载并执行,这样就会阻塞后续的文档解析。
<script src="test.js" defer>
<script src="test.js" async>
defer和async可以用来控制外部脚本的执行。首先可以看看解释。
defer:用于开启新的线程下载脚本文件,并使脚本在文档解析完成后执行。
async:HTML5新增属性,用于异步下载脚本文件,下载完毕立即解释执行代码。
那defer与async有什么本质区别呢?
defer加载后续文档元素的过程将和 script.js 的加载并行进行(异步),但 script.js 的执行要在所有元素解析完成之后,DOMContentLoaded 事件触发之前完成,所以如果是脚本并没有外部引用不要使用defer。
async加载和渲染后续文档元素的过程将和 script.js 的加载与执行并行进行(异步),其他线程将下载脚本,文档的解析不会停止,脚本下载完成后开始执行脚本,脚本执行的过程中文档将停止解析,直到脚本执行完毕。
所以async和defer的最主要的区别就是async是异步下载,下载完后立即执行,不影响文档的解析,defer是异步加载后解析文档。
如果有多个defer脚本,会按照顺序下载解析。而多个async脚本下载与解析的顺序是不一定的,所以如果脚本之间有依赖关系不要用async。
参考详解defer和async的原理及应用,实例可以查看这篇文章。