每位前端开发者都应了解的 5 个 JavaScript API
面向前端开发者的5个原生 JavaScript API:IntersectionObserver、ResizeObserver、AbortController、Clipboard API 和 View Transitions。
目前最值得学习的五个原生浏览器 API 分别是:IntersectionObserver、ResizeObserver、AbortController、Clipboard API 和 View Transitions API。它们每一个都能以平台原语的形式替代某个常见的第三方依赖,并且已内置于所有主流浏览器中。
我们大多数人都曾走过弯路——为了一个复制按钮引入了整个库,或者因为搜索框不断渲染过时结果而浪费了大半天时间,事后才发现浏览器本身早就提供了解决方案。如果你已经熟悉 fetch、localStorage 和 DOM 操作,但还没用过较新的 Observer 和工具类 API,这份清单能帮你删掉一两个依赖包。以下所有内容均为原生 Web 平台 API,而非 TMDB 或 Unsplash 这类托管 REST 服务,因此无需密钥、无需服务器,除了你已经在使用的浏览器之外没有任何运行时开销。每个条目都包含一句话定义、最小可运行示例、真实使用场景,以及客观的兼容性说明。
核心要点
- IntersectionObserver 无需滚动监听器即可报告元素何时进入或离开视口,自 2019 年 3 月起已成为跨浏览器的 Baseline 标准。
- ResizeObserver 响应的是元素自身的内容盒或边框盒尺寸变化,这正是实现容器感知组件的关键所在——而 window 的
resize事件对此无能为力。 - AbortController 是解决 React 竞态条件的标准方案:将
controller.signal传入fetch,并在 effect 清理函数中调用controller.abort(),从而防止过时响应覆盖最新的 UI 状态。 navigator.clipboard.writeText()是document.execCommand('copy')这一旧式方案的基于 Promise 的现代替代,但它只能在安全上下文(HTTPS 或 localhost)下运行。- 同文档 View Transitions 于 2025 年 10 月 14 日达到 Baseline Newly Available 状态,并能优雅降级,因此可以安全地在
if (document.startViewTransition)条件判断下上线使用。
IntersectionObserver:替代滚动监听器的 Web API
IntersectionObserver 以异步方式报告目标元素何时进入或离开视口(或任意祖先元素),让你无需任何滚动监听器即可实现懒加载、无限滚动和可见性埋点——自 2019 年 3 月起,它已成为跨浏览器的 Baseline 标准。滚动监听器每秒会在主线程上触发数十次,并且需要你自行计算几何信息;而 IntersectionObserver 会将这些工作批量处理,脱离关键渲染路径,仅在可见性真正发生变化时才回调你的函数。
const observer = new IntersectionObserver((entries) => {
for (const entry of entries) {
if (entry.isIntersecting) {
entry.target.src = entry.target.dataset.src; // 仅在可见时加载
observer.unobserve(entry.target);
}
}
});
document.querySelectorAll('img[data-src]').forEach((img) => observer.observe(img));
这段代码实现了图片随行滚入视口时的懒加载。同样的 isIntersecting 判断也可用于驱动无限滚动的哨兵元素和”已浏览”埋点事件。对长列表页面的会话回放清晰地展示了其收益:屏幕外的图片和追踪事件只在对应行进入视口时才触发,而非在页面加载时全部执行。对于大多数场景,它可以替代 react-intersection-observer 和手写的滚动计算逻辑。(注意:trackVisibility 选项仍处于实验阶段,尚未成为 Baseline 标准,建议只使用 isIntersecting。)
Discover how at OpenReplay.com.
ResizeObserver:元素级别的尺寸变化响应
当组件需要响应自身尺寸变化时,请使用 ResizeObserver,而非 window 的 resize 事件——它能报告元素级别的内容盒和边框盒尺寸变化,这正是实现容器感知组件的基础。window.resize 处理器只能告诉你视口发生了变化,却无法感知某个面板因侧边栏展开而收窄的情况。
const ro = new ResizeObserver((entries) => {
for (const entry of entries) {
const { width } = entry.contentRect;
entry.target.classList.toggle('is-narrow', width < 400);
}
});
ro.observe(document.querySelector('.card'));
在这个示例中,卡片根据自身宽度切换为紧凑布局——这本质上是一个用 JavaScript 实现的容器查询。它已在主流浏览器中成为 Baseline 标准,可替代 element-resize-detector 等库。如果你在控制台看到 ResizeObserver loop 警告,大多数情况下这是无害的,意味着你在回调函数内部修改了元素尺寸。
AbortController:取消请求并修复竞态条件
AbortController 是解决 React 竞态条件的标准方案:将 controller.signal 传入 fetch,在 effect 清理函数中调用 controller.abort(),即可确保过时的响应永远不会在快速重新导航后覆盖最新的 UI。AbortSignal 自 2018 年 4 月起已在各主流浏览器中可用。
useEffect(() => {
const controller = new AbortController();
fetch(`/api/results?q=${query}`, { signal: controller.signal })
.then((res) => res.json())
.then(setResults)
.catch((err) => {
if (err.name !== 'AbortError') throw err;
});
return () => controller.abort(); // 在卸载或新查询时取消请求
}, [query]);
这段代码消灭的是一个在会话回放中表现得格外明显的经典 bug:用户快速输入时,一个较早发出的慢速响应最后才到达,导致过时数据覆盖了当前视图。在清理函数中中止进行中的请求,使这种情况从根本上不可能发生。
对于纯超时场景,你可以跳过手动创建 controller。AbortSignal.timeout() 自 2024 年 4 月起已在各主流浏览器中可用,超时后会以 TimeoutError 中止请求;而用户主动触发的中止则抛出 AbortError,因此一个 catch 块即可区分两者:
fetch(url, { signal: AbortSignal.timeout(5000) });
这可以替代 isMounted 标志位和 axios.CancelToken。
Clipboard API:告别 execCommand 的复制粘贴方案
navigator.clipboard.writeText() 是 document.execCommand('copy') 旧式方案的现代替代,基于 Promise,但请注意它只能在安全上下文(HTTPS 或 localhost)下运行。
copyBtn.addEventListener('click', async () => {
await navigator.clipboard.writeText(snippet);
copyBtn.textContent = 'Copied!';
});
这正是各文档站点上”复制代码片段”按钮的实现方式。写入操作已是 Baseline 标准,可靠性高;读取操作则属于尽力而为。readText() 在剪贴板无文本内容时会返回空字符串,且 Firefox 对其限制比写入更为严格,因此复制是可靠的路径,而读取粘贴板内容最好作为渐进增强来处理。它可以替代 clipboard.js。
View Transitions API:原生动画化 DOM 状态切换
View Transitions 通过 document.startViewTransition(() => updateDOM()) 在 DOM 状态之间添加过渡动画,并且能够优雅降级(在不支持的浏览器中没有动画,但 DOM 仍会正常更新),因此今天就可以安全地在 if (document.startViewTransition) 条件判断下上线。同文档过渡于 2025 年 10 月 14 日达到 Baseline Newly Available 状态,支持 Chrome 111+、Edge 111+、Firefox 144+ 和 Safari 18+。
function updatePage(newContent) {
if (!document.startViewTransition) {
render(newContent); // 降级方案:立即更新,无动画
return;
}
document.startViewTransition(() => render(newContent));
}
适用于标签页切换、列表到详情的导航以及筛选状态变化——即那些你原本需要引入 Framer Motion 才能实现的交叉淡入和共享元素变形效果。startViewTransition() 的条件判断确保了不支持的浏览器会直接应用变更。需要注意的是,跨文档过渡的支持范围更窄:仅限 Chrome 126+、Edge 126+ 和 Safari 18.2+,Firefox 尚不支持,请勿将两者混淆。
额外补充:structuredClone 与 fetch 的注意事项
在下一个任务中选择上述 API 之一并删掉它所替代的依赖:用 IntersectionObserver 替换滚动监听器,或者用 AbortController 包裹搜索请求。还有一个值得随手备用的 API:structuredClone() 无需 JSON.parse(JSON.stringify(...)) 的迂回操作即可深拷贝对象,并且能正确处理 Date、Map、Set 和类型化数组——但它会对函数和 DOM 节点抛出 DataCloneError,因此适用于数据对象而非活动对象(自 2022 年 3 月起成为 Baseline 标准)。另外,如果你仍在使用 fetch 作为基础,请记住其 Promise 不会在 HTTP 404 或 500 时 reject,只有在网络故障时才会 reject,因此需要自行检查 response.ok。
常见问题
IntersectionObserver 和 ResizeObserver 有什么区别?
IntersectionObserver 报告元素何时进入或离开视口或某个祖先元素,因此适用于懒加载、无限滚动和可见性埋点。ResizeObserver 报告元素自身内容盒或边框盒尺寸的变化,因此适用于容器感知布局。IntersectionObserver 回答的是“这个元素是否可见?”,ResizeObserver 回答的是“这个元素有多大?”。两者解决的是不同问题,也都无法替代 `window` 的 `resize` 事件在视口级别的作用。
取消 fetch 请求时,应该使用 AbortSignal.timeout() 还是手动创建 AbortController?
如果只需要固定超时,使用 AbortSignal.timeout()——它会在指定毫秒数后自动以 TimeoutError 中止请求,无需 controller 变量。如果取消操作由你控制的事件触发,例如 React effect 在卸载或重新导航时的清理,则使用手动创建的 AbortController,由你自行调用 controller.abort()。两者抛出的错误不同——分别是 TimeoutError 和 AbortError——因此一个 catch 块即可区分。
为什么 navigator.clipboard.writeText() 在我的本地开发环境中失败了?
navigator.clipboard.writeText() 只能在安全上下文中运行,即 HTTPS 或 localhost。如果你通过普通 HTTP 地址访问开发服务器,例如本地 IP 或非 localhost 的主机名,浏览器会阻止剪贴板写入操作,Promise 将会 reject。请使用 localhost 或通过 HTTPS 提供服务。readText() 的限制更为严格,尤其在 Firefox 中,因此建议将写入作为可靠路径,将读取粘贴板内容作为渐进增强来处理。
如果部分浏览器不支持 View Transitions API,使用它是否安全?
是的,因为它能优雅降级。在调用前加上 if (document.startViewTransition) 的条件判断;在不支持的浏览器中,DOM 更新仍会执行,只是会立即生效而没有动画。同文档过渡于 2025 年 10 月 14 日达到 Baseline Newly Available 状态,支持 Chrome 111+、Edge 111+、Firefox 144+ 和 Safari 18+。跨文档过渡的支持范围更窄,仅限 Chrome 126+、Edge 126+ 和 Safari 18.2+,Firefox 尚不支持。
Gain control over your UX
See how users are using your site as if you were sitting next to them, learn and iterate faster with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data.
Star on GitHub12k