script标签的defer和async属性的作用

1,589 阅读2分钟

script的defer和async的用法

在我们通过script标签引入外部的js文件的时候通常会将script标签写在body的最下面,body结束标签的上面。

 <html>
     <head>
         ...
     </head>
     <body>
         ...
         <script src="...."></script>
     </body>
 </html>

这是因为在页面加载的时候会从上往下加载页面内容,当页面内容加载完成后再加载js的内容,这样就不回阻塞页面,让用户看到的空白页面时间减少些。如果将script写在网页内容上面,那么js引擎遇到script就会先加载js内容(下载,解析,运行),而网页的内容会在js文件运行完毕之后才会加载,所以用户会先看到空白页面,等待js运行完成才会呈现网页内容。

JavaScript标准给script提供了两个属性,用来设置脚本下载和执行的时间

推迟执行脚本

HTML4.01为script标签提供了一个defer属性,这个脚本表示该脚本在执行的时候不会改变页面结构,因此,这个脚本会在整个页面解析完成之后再执行,再script上加上defer属性会告诉浏览器,当遇到这个脚本的时候立即去下载这个脚本,但是执行会在页面解析完成后进行。

 <html>
     <head>
         <title>...</title>
         <script defer src="example1"></script>
         <script defer src="example2"></script>
     </head>
     <body>
         ....
     </body>
 </html>

在上面的例子中,虽然script在head标签中,但是只会下载,不会执行,在解析完之后才会执行,并且会根据他们出现的顺序依次执行,并且两者会在DOMContentloaded事件之前执行。

异步执行脚本

HTML5为script标签提供了async属性,梳理方式与defer大致相同,都不会导致页面渲染时间延迟。

 <html>
     <head>
         <title>...</title>
         <script async src="example1"></script>
         <script async src="example2"></script>
     </head>
     <body>
         ....
     </body>
 </html>

当解析到有async的script标签的时候,会通知浏览器立即下载该脚本,但是执行是异步的(个人理解的异步执行是在js引擎空闲的时候执行,宏观上是跟页面渲染同步的,微观上是异步交替执行的),而且执行的时候也不会根据它们的的出现顺序来执行,例如上面的例子,可能example2先于example1执行,也可能example1先于example2执行。但是脚本都会在页面的load事件前执行,但可能会在DOMContentloaded之前或之后。

总结

defer和async都不会延迟页面的渲染时间,在浏览器解析到有defer或者async的script标签时候都会立即下载,但是有defer的script标签会在解析结束后执行,async会异步执行。