在开发网页时,我们经常需要引入 JavaScript 脚本。但如果不注意加载方式,页面可能会卡顿甚至白屏。这时候,defer 和 async 就派上用场了。它们都用于控制外部脚本的加载和执行时机,但行为完全不同。
默认情况下的脚本加载
如果不加任何属性,直接写 <script src="app.js"></script>,浏览器会停下来,先下载并执行这个脚本,才能继续解析后面的 HTML。就像你在排队买奶茶,前面有人插队做定制款,你只能干等着。
async:异步加载,谁快谁先执行
加上 async 后,脚本会在后台下载,不阻塞页面渲染。一旦下载完成,立即中断渲染,优先执行它。
<script async src="analytics.js"></script>
<script async src="ads.js"></script>
这两个脚本谁先下完谁先执行,顺序不保证。适合那些不需要等待其他脚本、也不被其他脚本依赖的独立功能,比如统计代码或广告脚本。
defer:延迟执行,等页面解析完再运行
而 defer 也是异步下载,但它会等到整个 HTML 文档解析完成后,才按顺序执行。
<script defer src="lib.js"></script>
<script defer src="main.js"></script>
虽然两个脚本可能同时在下载,但执行时会严格按照顺序:先 lib.js,再 main.js。这特别适合有依赖关系的脚本,比如先加载库,再运行业务代码。
实际场景对比
假设你在一个电商页面嵌入了三个脚本:用户行为统计、商品推荐引擎、购物车逻辑。
- 统计脚本可以用
async,反正它独立运行,早点上报数据更好; - 推荐引擎依赖基础库,必须等库加载完才能跑,就得用
defer; - 购物车涉及核心交互,最好也用
defer,确保 DOM 解析完再绑定事件。
兼容性和使用建议
现代浏览器都支持 defer 和 async,老版本 IE 可能只支持 async 的部分行为。如果项目还要兼容很老的环境,得额外处理。
一般建议:
- 第三方独立脚本(如广告、统计)用
async; - 自身有依赖关系的 JS 文件用
defer; - 别在
<head>里放没有async或defer的外链脚本,那会让页面卡住。