defer和async的适用场景?

在script标签中加上defer属性效果是不是等同于把script放在</body>前,async异步加载js文件,加载完成后立即执行,那么async会不会在dom加载完之前就执行了,如果是这样的话,那么它的适用场景是什么

阅读 9.9k
3 个回答

1.defer的延迟加载确实十分类似把script放在</body>前,不过不能说是等同,因为defer属性的script外部文件的下载是与html解析线程同时进行的,而最后的执行时放在html解析的最后面,所以说效果类似,但是区别在于节省了外部script下载的时间。

2.async是加载完成后立即执行,所以会在dom加载完之前执行,在async执行完之后,html再继续解析。

3.我理解的两者的适应场景其实都主要在于“异步下载”这个点,所以当有多个外部脚本时可以节省很多下载时间,两者的区别体现在因为多个带async属性的外部脚本下载后的执行顺序不确定,所以适合没有相互依赖关系的多个外部脚本使用,而多个defer属性的外部脚本一般来说会按照顺序进行执行。

4.还有一些具体的可以参考下之前sf里面的一篇博客和一个问答,说得都挺好
浅谈script标签的defer和async
defer和async的区别

defer 和 async 在网络下载这块儿是一样的,相较于 HTML 解析都是异步的。不同点在于脚本下载完之后何时执行,defer是在HTML完全解析后再最后执行,async是下载完立即执行

之前写了一篇介绍 <script> 标签的 deferasync 属性 的文章,只需要 10 分钟即可看完,可以详细的了解他们的「区别」与「最佳实践」,建议阅读。

这里把总结列出来,可以看一下,快速了解:

defer

  • 不阻塞浏览器解析 HTML,等解析完 HTML 之后,才会执行 script
  • 会并行下载 JavaScript 资源。
  • 会按照 HTML 中的相对顺序执行脚本。
  • 会在脚本下载并执行完成之后,才会触发 DOMContentLoaded 事件。
  • 在脚本执行过程中,一定可以获取到 HTML 中已有的元素。
  • defer 属性对模块脚本无效。
  • 适用于:所有外部脚本(通过 src 引用的 script)。

async

  • 不阻塞浏览器解析 HTML,但是 script 下载完成后,会立即中断浏览器解析 HTML,并执行此 script
  • 会并行下载 JavaScript 资源。
  • 互相独立,谁先下载完,谁先执行,没有固定的先后顺序,不可控。
  • 由于没有确定的执行时机,所以在脚本里面可能会获取不到 HTML 中已有的元素。
  • DOMContentLoaded 事件和 script 脚本无相关性,无法确定他们的先后顺序。
  • 适用于:独立的第三方脚本。
另外:asyncdefer 之间最大的区别在于它们的执行时机。

还有就是这张非常经典的图:

image.png

推荐问题
宣传栏