003-script 的 async 跟 defer 的区别?

为什么 script 标签有 async 和 defer 这两个属性,因为浏览器在执行 HTML 时,如果遇到 <script> 会停止页面的渲染,去下载和执行 js 的文件直到 </script> 为止,才会继续渲染页面。故浏览器在执行 js 文件时浏览器表现为一片空白。

defer

这个属性就是延迟脚本到整个网页解析完成后再执行。HTML5 规范要求脚本按照它们出现的先后顺序执行,因此第一个延迟脚本会先于第二个延迟脚本执行,而这两个脚本会先于 DOMContentLoaded 事件执行。如果是内嵌脚本(缺少 src),不建议使用该属性,因为不起作用。

async

这个属性和 defer 类似,都用于改变处理脚本的行为。指示浏览器是否在允许的情况下异步执行该脚本。async 只适用于外部脚本文件,并告诉浏览器立即下载文件。但与 defer 不同的是,标记为 async 的脚本并不保证按照它们的先后顺序执行,而是先下载完的先执行,所以使用 async 的文件不应该有相互依赖关系。

区别

相同点:

  • 加载文件时不阻塞页面渲染。
  • 对于内嵌的脚本无效,当 script 标签中间有代码时,两个属性都不起作用。
  • 使用这两个属性的脚本中不能调用 document.write 方法
  • 有脚本的 onload 的事件回调

不同点:

  • HTML4 定义了 defer;HTML5 定义了 async,浏览器支持不同。
  • 每一个 async 属性的脚本都在它下载完成后执行,同时会在 window.load 事件之前执行。所以就有可能出现脚本执行顺序被打乱的情况;每个 defer 属性的脚本都是在页面解析完成后,按照脚本的顺序执行,同时会在 document 的 DOMContentLoaded 之前执行。

当一个 script 标签同时包含 defer 与 async 属性时,只会触发 async,除非浏览器不兼容 async 才会触发 defer

部分答案整理自网络资源