《JavaScript 进阶之旅》——async 和 defer,它们到底有什么区别?
在网页开发中,我们经常需要引入外部 JavaScript 脚本。而 <script> 标签的两个属性 —— async 和 defer,常常让人感到困惑:它们都用于控制脚本的加载和执行方式,但具体有什么不同呢?这篇文章将带你深入理解这两个属性的区别,并通过代码示例帮助你更好地掌握它们的应用场景。
一、先来回顾一下默认行为
在没有使用 async 或 defer 的情况下,浏览器会如何处理 <script> 标签?
Html
<script src="script.js"></script>
在这种情况下:
HTML 解析会被暂停(即“阻塞”);
浏览器开始下载 script.js 文件;
下载完成后,立即执行脚本;
执行完毕后继续解析 HTML。
这会导致页面渲染被阻塞,影响性能,特别是在网络较慢或脚本较大的情况下。
二、defer:等我一会儿,我马上就好
使用 defer 属性可以让浏览器异步加载脚本,但等到 HTML 文档完全解析后再执行。
示例代码:
Html
<script defer src="defer-script.js"></script>
特点总结:
异步加载,不会阻塞 HTML 解析;
脚本会在 文档解析完成之后、DOMContentLoaded 事件之前 执行;
多个带有 defer 的脚本会按照它们在 HTML 中的顺序执行。
适用场景:
脚本依赖页面 DOM 元素;
需要多个脚本按顺序执行;
希望提升页面加载速度但又不影响脚本逻辑。
三、async:谁先下完谁先跑
使用 async 属性会让脚本异步加载并立即执行,一旦下载完成就会运行,不等待文档解析完成。
示例代码:
Html
<script async src="async-script.js"></script>
特点总结:
异步加载,不阻塞 HTML 解析;
下载完就执行,执行顺序不确定;
不保证多个 async 脚本之间的执行顺序;
执行过程中仍会阻塞渲染(虽然不会阻塞 HTML 解析);
适用场景:
脚本不依赖页面 DOM;
脚本之间不需要顺序依赖;
希望尽可能早地执行脚本,比如统计脚本、广告脚本等。
四、对比表格:清晰明了
特性 | 默认行为 | defer | async |
是否阻塞 HTML 解析 | 是 | 否 | 否 |
是否异步加载 | 否 | 是 | 是 |
执行时机 | 立即执行 | 文档解析完成后 | 下载完成后立即执行 |
执行顺序 | 按顺序 | 按顺序 | 不确定 |
五、实战演练:看效果!
下面是一个完整的 HTML 页面,展示了三种加载方式的不同行为。
HTML 示例:
Html
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>Script 加载测试</title>
<!-- 默认行为 -->
<script src="default.js"></script>
<!-- defer -->
<script defer src="defer.js"></script>
<!-- async -->
<script async src="async.js"></script>
</head>
<body>
<h1>Hello, JavaScript!</h1>
<p>这是测试内容。</p>
</body>
</html>
对应脚本文件内容:
default.js:
Javascript
console.log("Default Script: 我是同步加载的");
defer.js:
Javascript
console.log("Defer Script: 我会在文档解析完成后执行");
async.js:
Javascript
console.log("Async Script: 我一下载完就执行");
控制台输出可能为:
Async Script: 我一下载完就执行
Default Script: 我是同步加载的
Defer Script: 我会在文档解析完成后执行
或者根据下载速度不同,async 的顺序可能会变化。
六、什么时候该用哪个?
使用场景 | 推荐属性 |
脚本依赖DOM需顺序执行 | defer |
无需顺序执行 | async |
脚本很小且必须尽快执行 | async |
脚本较大,希望不影响页面渲染 | defer |
脚本在 <head> 中,想避免阻塞 | defer 或 async |
脚本在 <body> 结尾处,可省略 | 不需要设置 |
七、小结
async 和 defer 都可以让你的页面更快加载,但它们的行为有本质区别;
defer 适合那些需要操作 DOM 或需要顺序执行的脚本;
async 更适合那些独立、快速执行的小脚本;
合理使用它们可以显著提升网页性能和用户体验。