浅谈javascript中的defer、async

本文详细阐述HTML5中defer与async属性的功能及差异。两者都能实现脚本加载的异步化,但defer保证脚本按顺序执行且在DOMContentLoaded前完成,而async脚本加载后即执行,可能导致乱序。

转载自http://www.cnblogs.com/dreamGong/p/5125030.html
引言
  开始重读《JavaScript高级程序设计》一书,看到关于JavaScript中关于defer、async的部分。网上查询了点资料,觉得蛮好的。现在总结下。

defer/async(Html5新增)
  首先我们来看一下在

<script type="text/javascript" defer="defer" async="true/false" src="js文档地址"></script>

下面我们一个一个来看,看看这两个属性的设置对于JavaScript文件加载和执行的影响。

  1、<script src="script.js"></script>

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

  2、<script async src="script.js"></script>

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

  3、<script defer src="myscript.js"></script>

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

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

  下面我们通过一张形象的图来更加直观的解释这两个属性。
  这里写图片描述
  蓝色线代表网络读取,红色线代表执行时间,这俩都是针对脚本的;绿色线代表 HTML 解析。

  此图告诉我们以下几个要点:
  

  • defer 和 async 在网络读取(下载)这块儿是一样的,都是异步的(相较于 HTML 解析)
  • 它俩的差别在于脚本下载完之后何时执行,显然 defer 是最接近我们对于应用脚本加载和执行的要求的
  • 关于 defer,此图未尽之处在于它是按照加载顺序执行脚本的,这一点要善加利用
  • async 则是一个乱序执行的主,反正对它来说脚本的加载和执行是紧紧挨着的,所以不管你声明的顺序如何,只要它加载完了就会立刻执行
  • 仔细想想,async 对于应用脚本的用处不大,因为它完全不考虑依赖(哪怕是最低级的顺序执行),不过它对于那些可以不依赖任何脚本或不被任何脚本依赖的脚本来说却是非常合适的,最典型的例子:Google Analytics

defer和async的比较
  相同点:
- 加载文件时不阻塞页面渲染;
- 对于inline的script无效;
- 使用这两个属性的脚本中不能调用document.write方法;
- 有脚本的onload的事件回调;
- 允许不定义属性值,仅仅使用属性名;
 不同点:
- html的版本html4.0中定义了defer;html5.0中定义了async;这将造成由于浏览器版本的不同而对其支持的程度不同;
- 执行时刻:每一个async属性的脚本都在它下载结束之后立刻执行,同时会在window的load事件之前执行。所以就有可能出现脚本执行顺序被打乱的情况;每一个defer属性的脚本都是在页面解析完毕之后,按照原本的顺序执行,同时会在document的DOMContentLoaded之前执行。
这两个属性会有三种可能的组合:
- 如果async为true,那么脚本在下载完成后异步执行。
- 如果async为false,defer为true,那么脚本会在页面解析完毕之后执行。
- 如果async和defer都为false,那么脚本会在页面解析中,停止页面解析,立刻下载并且执行。

### HTML `script` 标签中 `defer` 与 `async` 属性的区别及用法 #### 基本定义 在 JavaScript 中,`<script>` 标签用于引入外部 JavaScript 文件或包含嵌入式 JavaScript 代码。为了优化页面加载性能并控制脚本的执行时机,HTML 提供了两种特殊的属性——`defer` 和 `async`。 #### `defer` 属性 当 `<script>` 标签带有 `defer` 属性时,浏览器会继续解析和渲染后续的文档内容,而不会阻塞 DOM 构建过程[^3]。脚本会在整个 HTML 文档解析完成后立即按顺序执行,这意味着如果页面中有多个带有 `defer` 属性的脚本,则它们会按照其在 HTML 中出现的顺序依次执行[^5]。 以下是使用 `defer` 的示例代码: ```html <script src="script1.js" defer></script> <script src="script2.js" defer></script> ``` #### `async` 属性 对于具有 `async` 属性的 `<script>` 标签,浏览器同样不会因为下载该脚本文件而停止解析其他部分的内容[^4]。然而,一旦脚本被成功获取回来之后就会立刻被执行,而不等待任何其他的资源或者操作完成。需要注意的是,这种行为可能导致不同脚本之间的执行次序变得不可预测,具体取决于各个请求返回的速度差异。 下面是一个简单的例子展示了如何应用 `async` 属性: ```html <script src="library.js" async></script> <script src="app.js"></script> <!-- 这里可能还未等到 library.js 加载完毕 --> ``` #### 主要对比 | 特性 | `normal (no attribute)` | `defer` | `async` | |-----------------|-------------------------------|----------------------------------|---------------------------------| | **下载阶段** | 阻挡DOM构建 | 并行下载 | 并行下载 | | **执行阶段** | 按照遇到的位置暂停解析直到运行完当前脚本 | 在DOMContentLoaded事件触发前依序执行 | 尽早尽可能快地单独执行 | 总结来说,在实际开发过程中可以根据需求选择合适的策略来提升网页的整体表现力。例如,如果你希望某些非关键性的第三方统计工具尽快发挥作用但又不影响主要业务逻辑的话,那么就可以采用 `async` 方式;而对于那些需要确保特定先后关系才能正常运作的部分则更适合运用 `defer` 技术[^1]。 ### 结论 通过上述分析可以看出,虽然两者都能实现异步加载效果从而改善首屏呈现速度等方面的优势,但是由于各自独特的特性决定了适用场景也有所不同。因此理解清楚两者的本质区别是非常重要的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值