主要决定了脚本加载的方式
一、核心区别对比表
| 特性 | 普通script | async | defer |
|---|---|---|---|
| 执行顺序 | 按书写顺序执行 | 谁先加载完谁先执行(无序) | 按书写顺序执行(有序) |
| 执行时机 | 立即执行,阻塞渲染 | 加载完立即执行,可能阻塞渲染 | DOM解析完成后执行,不阻塞渲染 |
| 适用场景 | 无依赖的独立脚本 | 统计代码、广告脚本 | 有依赖关系的脚本(如jQuery插件) |
| DOM访问 | 可能访问不完整DOM | 可能访问不完整DOM | 可以访问完整DOM |
二、执行时序图解析(重点!)
普通script:
HTML解析 -> 遇到script -> 暂停解析 -> 下载执行 -> 继续解析
async:
HTML解析 -> 遇到script -> 并行下载 -> 下载完成立即执行 -> 继续解析
defer:
HTML解析 -> 遇到script -> 并行下载 -> HTML解析完成 -> 按顺序执行
三、代码示例验证
<!DOCTYPE html>
<html>
<head>
<!-- 异步加载 -->
<script async src="async1.js"></script>
<script async src="async2.js"></script>
<!-- 延迟执行 -->
<script defer src="defer1.js"></script>
<script defer src="defer2.js"></script>
</head>
<body>
<div>页面内容...</div>
</body>
</html>
假设加载速度:
- async2.js 比 async1.js 先加载完
- defer1.js 和 defer2.js 按顺序加载
执行顺序结果:
- async2.js 先执行(谁快谁先)
- async1.js 后执行
- defer1.js
- defer2.js(保持书写顺序)
四、高频面试题精讲
1. 如果同时使用async和defer会怎样?
<script async defer src="script.js"></script>
现代浏览器会优先采用async行为(当作async处理)
2. 怎么选择用async还是defer?
- 需要尽早执行且不依赖DOM → async(如网站统计代码)
- 有依赖关系或需要操作DOM → defer(如jQuery+Bootstrap)
3. 对DOMContentLoaded事件的影响
document.addEventListener('DOMContentLoaded', () => {
console.log('DOM解析完成');
});
- async脚本可能阻塞DOMContentLoaded
- defer脚本在DOMContentLoaded之前执行
五、记忆口诀
"异步async谁快谁先上,延迟defer顺序不能乱
普通脚本阻塞要小心,统计广告适合用异步"
配合对比表格和时序图理解,面试时如果被问到,可以这样回答:
"async和defer都能实现异步加载,但async是无序执行适合独立脚本,defer保持顺序适合依赖型脚本。实际开发中需要操作DOM的脚本建议用defer,像Google Analytics这种统计代码适合用async。"