关于Javascript中defer和async的区别总结

首先来看看这三句话:

<script src="https://www.jb51.net/script.js"></script>

没有 defer 或 async,浏览器会立即加载并执行指定的脚本,“立即”指的是在渲染该 script 标签之下的文档元素之前,也就是说不等待后续载入的文档元素,读到就加载并执行。

<script async src="https://www.jb51.net/script.js"></script>

有 async,加载和渲染后续文档元素的过程将和 script.js 的加载与执行并行进行(异步)。

<script defer src="https://www.jb51.net/myscript.js"></script>

有 defer,加载后续文档元素的过程将和 script.js 的加载并行进行(异步),但是 script.js 的执行要在所有元素解析完成之后,DOMContentLoaded 事件触发之前完成。

下面来进行详解的介绍这二者的区别。

一般情况

按照惯例,所有script元素都应该放在页面的head元素中。这种做法的目的就是把所有外部文件(CSS文件和JavaScript文件)的引用都放在相同的地方。可是,在文档的head元素中包含所有JavaScript文件,意味着必须等到全部JavaScript代码都被下载、解析和执行完成以后,才能开始呈现页面的内容(浏览器在遇到body标签时才开始呈现内容)。

对于那些需要很多JavaScript代码的页面来说,这无疑会导致浏览器在呈现页面时出现明显的延迟,而延迟期间的浏览器窗口中将是一片空白。为了避免这个问题,现在Web应用程序一般都全部JavaScript引用放在body元素中页面的内容后面。这样一来,在解析包含的JavaScript代码之前,页面的内容将完全呈现在浏览器中。而用户也会因为浏览器窗口显示空白页面的时间缩短而感到打开页面的速度加快了。

<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title></title> </head> <body> <script type="text/javascript" src="https://www.jb51.net/script.js"></script> </body> </html>

defer (延迟脚本)

延迟脚本:defer属性只适用于外部脚本文件。

如果给script标签定义了defer属性,这个属性的作用是表明脚本在执行时不会影响页面的构造。也就是说,脚本会被延迟到整个页面都解析完毕后再运行。因此,如果script元素中设置了defer属性,相当于告诉浏览器立即下载,但延迟执行。

示例:

<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>延迟加载</title> <script defer type="text/javascript" src="https://www.jb51.net/test.js"></script> </head> <body> </body> </html>

这个例子中,虽然我们把script元素放在了文档的head元素中,但其中包含的脚本将延迟到浏览器遇到</html>标签后再执行
HTML5规范要求脚本按照它们出现的先后顺序执行,因此第一个延迟脚本会先于第二个延迟脚本执行,而这两个脚本会先于DOMContentLoaded事件(在DOM树构建完成后触发,不需要等到所有的资源都加载完毕)执行。

特别注意:在现实当中,延迟脚本并不一定会按照顺序执行,也不一定会在DOMContentLoaded事件触发前执行,因此最好只包含一个延迟脚本。

有 defer,加载后续文档元素的过程将和 script.js 的加载并行进行(异步),但是 script.js 的执行要在所有元素解析完成之后,DOMContentLoaded 事件触发之前完成。

最佳实践

从实用角度来说,把所有脚本都放在 </body> 之前是最佳实践,因为对于旧浏览器来说这是唯一的优化选择,此法可保证非脚本的其他一切元素能够以最快的速度得到加载和解析。

**注意:**defer属性在浏览器之间表现并不一致。为了避免跨浏览器的差异,可以使用 “lazy loading”的方法,即直到用到该脚本时才加载。

function lazyload() { var elem = document.createElement("script"); elem.type = "text/javascript"; elem.async = true; elem.src = "https://www.jb51.net/script.js"; document.body.appendChild(elem); } if (window.addEventListener) { window.addEventListener("load", lazyload, false); } else if (window.attachEvent) { window.attachEvent("onload", lazyload); } else { window.onload = lazyload; }

async(异步脚本)

异步脚本:async属性也只适用于外部脚本文件,并告诉浏览器立即下载文件。

但与defer不同的是:标记为async的脚本并不保证按照指定它们的先后顺序执行。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wzjjxf.html