script标签中的defer和async区别

script标签的位置决定了页面何时渲染,浏览器解析页面时,碰到script标签会将脚本解析完后再解析后面的html、script。

所以我们在往页面里写script标签时建议不要将script标签放在head内,而是尽量放在body之前,其他html标签之后。这样的好处是页面白屏时间会缩短,优先解析出html。

定义

红宝书对这两个属性的解释如下:

defer

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

HTML5规范要求脚本按照它们出现的先后顺序执行,因此第一个延迟脚本会先于第二个延迟脚本执行,而这两个脚本会先于DOMContentLoaded事件执行。在现实当中,延迟脚本并不一定会按照顺序执行,也不一定会在DOMContentLoad事件触发前执行,因此最好只包含一个延迟脚本。

async

这个属性与defer类似,都用于改变处理脚本的行为。同样与defer类似,async只适用于外部脚本文件,并告诉浏览器立即下载文件。但与defer不同的是,标记为async的脚本并不保证按照它们的先后顺序执行。

第二个脚本文件可能会在第一个脚本文件之前执行。因此确保两者之间互不依赖非常重要。指定async属性的目的是不让页面等待两个脚本下载和执行,从而异步加载页面其他内容。

MDN上的解释如下:

  • async,该布尔属性指示浏览器是否在允许的情况下异步执行该脚本。该属性对于内联脚本无作用 (即没有src属性的脚本)。
  • defer,这个布尔属性被设定用来通知浏览器该脚本将在文档完成解析后,触发DOMContentLoaded事件前执行。如果缺少 src 属性(即内嵌脚本),该属性不应被使用,因为这种情况下它不起作用。对动态嵌入的脚本使用 async=false 来达到类似的效果。

关键点:当script标签中间有代码时,两个属性都不会起作用。

引用中这篇文章的图,描述页面加载的顺序:

defer_async.jpg

绿色线代表 HTML 解析,蓝色线代表脚本网络读取,红色线代表脚本执行。

  • 没有任何属性时,文档解析、网络读取、执行都是串行。
  • defer时文档解析与网络读取并行,在文档解析后,DOMContentLoaded事件触发之前执行
  • async则没有任何限制,文档解析时网络读取文件,读取完后立即执行。

使用时机与场景请自行琢磨~

优先级

当一个script标签内同时包含deferasync属性时,如下:

1
<script src="xxx/xxx.js" async defer></script>

此时只会触发async,不会触发defer,除非浏览器不兼容async

兼容性

IE Chrome Firfox Safari IOS Safari Android
async 10+ 8+ 3.6+ 5.1+ 5.1+ 3+
defer 10+ 8+ 3.5+ 5+ 5.1+ 3+

_*_ 以上 + 包含当前版本,如:ie10+表示含ie10

Powered by Hexo and Hexo-theme-hiker

Copyright © 2013 - 2019 FE blog All Rights Reserved.

访客数 : | 访问量 :