一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

async属性有何用途_HTML script标签async异步执行探究

时间:2026-06-10 10:29:57 编辑:袖梨 来源:一聚教程网

async脚本执行时DOM可能未就绪,导致document.getElementById返回null;它不等待HTML解析完成,下载完立即中断解析执行,故常在head中操作body节点时报错。

async 属性让外部脚本异步下载、下载完立即执行,但不保证执行顺序,也不等 DOM 就绪——它不是“无感加载”,而是“抢时机执行”。用错地方会直接导致 document.getElementById 返回 null$ is not defined

async 脚本为什么一执行就报 null?

因为 async 不等 HTML 解析完。浏览器遇到 <script src="app.js" async></script>,一边下载 app.js,一边继续解析页面;一旦下载完成,立刻中断解析、执行脚本。此时若脚本里写了 document.getElementById('header'),而 <div id="header"> 还没解析到,结果就是 null

  • 常见错误现象:Uncaught TypeError: Cannot read property 'addEventListener' of null
  • 典型位置陷阱:把 async 脚本放在 <head> 里,却在脚本中操作 <body> 下的节点
  • 根本原因:async 的执行时机由下载速度决定,与 DOM 构建进度无关
  • 验证方式:在脚本开头加 console.log(document.body === null),大概率输出 true

async 和 defer 到底该选哪个?

看脚本是否依赖 DOM 或其他脚本。

  • async:脚本完全独立,不读 DOM、不调其他 JS、失败不影响主流程(如 analytics.jsads.js
  • defer:要操作 document、绑定事件、或和前一个 src 脚本有依赖(如先 jquery.jsplugin.js
  • 别混用:asyncdefer 同时存在时,浏览器按规范忽略 defer,只认 async
  • 内联脚本不生效:<script defer>console.log(1)</script> 中的 defer 会被浏览器忽略,只对带 src 的外部脚本有效

async 脚本执行时会卡页面吗?

会。虽然下载不阻塞 HTML 解析,但执行时浏览器必须暂停解析、交出主线程,直到脚本运行完。如果脚本里有大量同步计算或长任务,用户会感知到短暂卡顿,首屏渲染时间(LCP)可能被拉长。

立即学习“前端免费学习笔记(深入)”;

  • 性能影响点:大体积 async 脚本(比如 >200KB)下载快但执行慢,容易成为渲染瓶颈
  • 对比 defer:defer 执行时 DOM 已就绪,且多个 defer 脚本按序排队,更利于主线程调度
  • 替代方案:对非关键逻辑,优先考虑动态 import() 或 setTimeout(() => { ... }, 0) 延后执行
  • 兼容性提醒:async 在 IE9 及以下完全不支持,现代项目虽可忽略,但若需兼容旧企业内网环境,得 fallback 到动态创建 script 标签

真正难处理的不是 async 本身,而是脚本内部隐式依赖:比如某个统计 SDK 看似独立,实则内部调用了 performance.getEntries(),而这个 API 在某些低端 Android WebView 中需 DOM 就绪后才稳定可用——这种边界情况,光靠属性声明解决不了,得结合 onload 回调和特征检测兜底。

热门栏目