JS脚本加载中,defer和async的区别
在HTML页面中插入JavaScript的主要方法包括内联脚本和外联脚本。内联脚本直接在页面中嵌入JavaScript代码,而外联脚本则引用外部JavaScript文件。在浏览器加载HTML过程中,遇到<script>标签时,默认情况下会阻塞HTML的解析和渲染,直到脚本被下载并执行完毕。这种行为被称为“渲染阻塞”。
为了解决这一问题,<script>标签提供了defer和async两个属性,它们允许浏览器异步加载脚本,从而避免阻塞HTML的解析和渲染。
1. async属性
- 行为:async属性指示浏览器在允许的情况下异步执行脚本。对于没有src属性的内联脚本,async属性不起作用。
- 执行时机:异步脚本会在下载完成后,尽快执行,但不一定在DOMContentLoaded事件触发之前或之后。此外,异步脚本的执行顺序不保证按照它们在HTML中出现的顺序。
- 适用场景:适用于那些不依赖于其他脚本、不需要等待整个文档解析完成的独立脚本。
2. defer属性
- 行为:defer属性通知浏览器,脚本将在文档完成解析后,但在DOMContentLoaded事件触发前执行。对于没有src属性的内联脚本,defer属性同样不起作用。
- 执行时机:延迟脚本会在整个HTML文档解析完成后执行,且按照它们在HTML中出现的顺序执行。
- 适用场景:适用于那些需要在文档解析完成后执行,但又不希望阻塞渲染过程的脚本。
3. 区别对比
- 加载方式:async和defer都是异步加载脚本,不会阻塞HTML的解析和渲染。
- 执行时机:async脚本在下载完成后尽快执行,可能在DOMContentLoaded事件之前或之后;而defer脚本在文档解析完成后执行,且保证执行顺序。
- 对HTML解析的影响:async脚本在下载和执行时可能会中断HTML的解析和渲染;而defer脚本则不会,它会在文档解析完成后统一执行。
- 适用场景:async更适合于独立、不依赖于其他脚本的异步任务;而defer更适合于需要在文档解析完成后按顺序执行的脚本。
4. 示例说明
通过Chrome的performance工具可以观察到,使用async和defer属性的脚本在加载和执行过程中的不同表现。
- 对于async脚本,浏览器的HTML解析和脚本下载是并行的,但脚本的执行可能会中断HTML的渲染。
- 对于defer脚本,浏览器的HTML解析和脚本下载同样是并行的,但脚本的执行会在文档解析完成后进行,且不会中断HTML的渲染。
总结
- async和defer都是用于异步加载JavaScript脚本的属性,但它们在执行时机和对HTML解析的影响上有所不同。
- 选择使用哪个属性取决于脚本的具体需求和依赖关系。如果脚本需要尽快执行且不需要等待文档解析完成,可以使用async;如果脚本需要在文档解析完成后按顺序执行,可以使用defer。