async适用于独立外部脚本,如统计、广告、监控等不依赖dom和其他脚本的场景;defer则用于需操作dom或有执行顺序依赖的脚本,确保在dom解析完成后按序执行。

直接用 async 属性就行,但必须是外部脚本,且不能依赖执行顺序。
什么时候该加 async?
适合那些「跟页面其他逻辑无关、不操作 DOM、也不被其他脚本依赖」的独立脚本,比如统计埋点、广告 SDK、错误监控上报。
- 用户行为上报脚本(
analytics.js)——早加载早发数据,不影响首屏 - 第三方客服 widget(
chat-widget.js)——晚一点出现也没关系 - 非关键路径的工具函数(
utils.js),且确认没被DOMContentLoaded之前的代码调用
反例:jQuery 插件、初始化轮播图的脚本、依赖 document.body 的 DOM 操作 —— 这些加 async 很可能报 Cannot read property 'xxx' of null。
async 和 defer 到底差在哪?
两者都不阻塞 HTML 解析,但执行时机完全不同:
-
async:下载完立刻执行,**可能打断 DOM 解析**,执行顺序不确定(谁先下完谁先跑) -
defer:下载和解析并行,但**所有 defer 脚本等 DOM 解析完再按顺序执行**,保证在DOMContentLoaded前
所以如果你有多个脚本,且第二个依赖第一个(比如 lodash.js + app.js),async 会出错,必须换 defer 或手动用 import() 控制。
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
常见错误现象和绕过方式
加了 async 却发现脚本报错、变量未定义、DOM 找不到元素 —— 八成是执行太早了。
- 错误写法:
<script async src="init.js"></script>,而init.js里写了document.querySelector('#header').textContent = 'Hi'; - 正确做法:要么改用
defer,要么把操作包进DOMContentLoaded回调:document.addEventListener('DOMContentLoaded', () => { /* DOM 操作 */ }); - 更稳妥的替代:动态创建 script 标签,手动控制插入时机:
const s = document.createElement('script'); s.src = 'init.js'; document.head.appendChild(s);(此时默认就是异步的)
注意:async 属性对内联脚本无效,<script async>console.log(1)</script> 中的 async 会被浏览器忽略。
兼容性和构建时要注意什么
async 是 HTML5 属性,IE9+、Chrome、Firefox、Safari 都支持,但 IE6–8 完全不识别 —— 不会报错,但会退化成同步加载,页面卡顿风险回升。
- 现代项目如果已放弃旧 IE,放心用;否则建议统一走构建工具(如 Webpack 的 code splitting)或动态 import
- Vite/Webpack 构建时,
import()生成的 chunk 默认带async行为,但本质是 fetch + eval,和原生async不是一回事,别混为一谈 - 服务端渲染(SSR)场景下,
async脚本不会在服务端执行,只影响客户端加载节奏,注意首屏内容是否被它拖慢
最常被忽略的一点:async 脚本里的 document.write 会清空整个页面,这个行为在现代开发中几乎没人测,但一旦误用就直接白屏。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










