1. defer 属性
工作机制
- 加载方式:当浏览器遇到带有 defer 属性的
<script>
标签时,会在后台下载该脚本文件,并且继续解析 HTML文档。这样可以确保文档的解析不会被阻塞。 - 执行顺序:所有的 defer 脚本会按照它们在文档中出现的顺序执行,并且只有在整个 HTML文档解析完成后才会执行。这确保了在执行脚本时,DOM 元素已经完全可用。
优缺点
- 优点:
-
保证了脚本的执行顺序,适合需要依赖其他脚本或 DOM 内容的情况。
-
不会阻塞 HTML 的解析,提高页面加载性能。
-
可以安全地操作 DOM,因为脚本在文档解析完成后执行。
- 缺点:
- 如果脚本较大且复杂,可能会导致文档解析完成后的首次交互稍有延迟。
适用场景
需要在 DOM 解析完成后执行的脚本,典型应用包括网站的主 JavaScript 文件、需要设置事件监听器的脚本等。
<script src="main.js" defer></script>
<script src="helper.js" defer></script>
2 async 属性
工作机制
- 加载方式:当浏览器解析到带有 async 属性的
<script>
标签时,它会立即开始下载该脚本,同时继续解析后续的 HTML文档。这意味着页面的其他内容不会因为这个脚本的加载而阻塞。 - 执行顺序:一旦脚本下载完成,浏览器会立即执行该脚本。由于网络状况和脚本文件大小的不同,多个 async脚本的执行顺序是不可预测的。这意味着如果有依赖关系的脚本,可能会出现问题。
优缺点
优点:
- 提升页面加载性能,因为脚本不会阻塞 HTML 文档的解析。
- 可以在加载脚本时继续处理页面内容,提高用户体验。
缺点:
- 执行顺序不确定,对于有依赖关系的脚本可能导致错误。
- 不保证在 DOM 完全可用之前执行,因此不适合需要操作 DOM 的代码。
适用场景
独立的脚本,比如第三方分析工具(如 Google Analytics)、广告或社交分享按钮等,这些脚本通常不依赖于文档的 DOM 结构。
<script src="analytics.js" async></script>
<script src="ad.js" async></script>
3. 比较总结
属性 | 加载方式 | 执行方式 | 执行顺序 | 适用场景 |
---|---|---|---|---|
defer | 在后台加载,不阻塞 HTML 解析 | 文档解析完成后按顺序执行 | 保证顺序 | 依赖 DOM 的脚本 |
async | 立即加载,不阻塞 HTML 解析 | 下载完成后立即执行 | 不保证 | 独立脚本(如分析工具、广告) |
4 如果 <script>
标签没有使用 async 或 defer 属性
浏览器的行为如下:
默认行为
加载方式:
- 浏览器在解析 HTML 文档时遇到
<script>
标签时,会立即停止解析文档,开始下载并执行该脚本。
执行顺序:
- 脚本会按它们在文档中出现的顺序依次执行。如果有多个脚本,它们会一个接一个地被加载和执行,直到所有脚本都执行完成后,浏览器才会继续解析后面的HTML 内容。
影响
- 阻塞渲染:由于脚本的下载和执行会阻止 DOM 的进一步解析,这可能导致页面渲染延迟,影响用户体验。
- 依赖问题:如果某些脚本依赖于其他脚本或 DOM 元素的存在,且这些脚本的顺序不正确,可能会导致错误。