Script 标签 defer 和 async
script 标签的 defer 和 async 属性区别及使用场景
问题
script 标签中 defer 和 async 的区别是什么?
解答
三种加载方式对比
<!-- 1. 普通 script:阻塞 HTML 解析 -->
<script src="script.js"></script>
<!-- 2. async:异步下载,下载完立即执行 -->
<script async src="script.js"></script>
<!-- 3. defer:异步下载,HTML 解析完后执行 -->
<script defer src="script.js"></script>
执行时序
普通 script:
HTML 解析 ──▶ 暂停 ──▶ 下载JS ──▶ 执行JS ──▶ 继续解析 ──▶ DOMContentLoaded
async:
HTML 解析 ─────────────────────────────────────▶ DOMContentLoaded
↓ 下载JS ──▶ 执行JS(随时可能打断解析)
defer:
HTML 解析 ──────────────────────────────────────▶ 执行JS ──▶ DOMContentLoaded
↓ 下载JS ─────────────────────────↑
实际使用示例
<!DOCTYPE html>
<html>
<head>
<!-- defer:适合依赖 DOM 的脚本,按顺序执行 -->
<script defer src="jquery.js"></script>
<script defer src="app.js"></script> <!-- 保证在 jquery.js 之后执行 -->
<!-- async:适合独立脚本,如统计、广告 -->
<script async src="analytics.js"></script>
</head>
<body>
<div id="app"></div>
</body>
</html>
验证执行顺序
<!DOCTYPE html>
<html>
<head>
<script>
document.addEventListener('DOMContentLoaded', () => {
console.log('DOMContentLoaded');
});
</script>
<script defer>
console.log('defer 脚本执行');
console.log('DOM 是否可用:', document.getElementById('app')); // 可用
</script>
</head>
<body>
<div id="app">Hello</div>
</body>
</html>
<!-- 输出顺序:
defer 脚本执行
DOM 是否可用: <div id="app">Hello</div>
DOMContentLoaded
-->
关键点
- 下载阶段:async 和 defer 都不阻塞 HTML 解析
- 执行时机:async 下载完立即执行;defer 等 HTML 解析完再执行
- 执行顺序:async 不保证顺序;defer 按文档顺序执行
- DOMContentLoaded:defer 脚本在该事件前执行;async 与该事件无关
- 使用场景:defer 用于依赖 DOM 或有依赖关系的脚本;async 用于独立的第三方脚本
目录