You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无布局重计算场景下ResizeObserver与window resize事件监听器的效率对比及验证方法

无布局重计算场景下ResizeObserver与window resize事件监听器的效率对比及验证方法

咱们先从你给出的示例说起——你写的这段代码里,ResizeObserver和window的resize事件回调执行次数、触发时机看起来完全一致,甚至Chrome 130 DevTools的输出也印证了这一点(除了ResizeObserver初始化时会多跑一次,这个细节你也注意到了)。那在这种没有布局读写操作、不会触发布局抖动的简单场景下,两者到底有没有效率差异呢?

核心结论

在你这种纯日志输出(或者无布局操作)的回调场景下,两者的性能差异几乎可以忽略不计,甚至可以认为是完全等价的。

为什么会这样?

ResizeObserver被推崇为更高效的方案,核心是针对普通DOM元素(比如<div>)的尺寸监听场景:

  • 当你监听普通DOM元素时,window的resize事件会在窗口变化时无脑触发,哪怕目标元素的尺寸根本没改变;但ResizeObserver只会在目标元素的尺寸真的发生变化时才触发回调,能避免大量冗余执行。
  • 之前关于“ResizeObserver比EventTarget更高效”的讨论,也都是针对普通DOM元素的——因为给普通元素绑定resize事件(还要处理冒泡等逻辑)的开销,远大于ResizeObserver的精准尺寸跟踪。

但你现在监听的是document.documentElement(也就是HTML根元素),它的尺寸变化和window的尺寸变化是强绑定的:窗口一 resize,根元素的尺寸必然跟着变,反之亦然。这种情况下,ResizeObserver和window resize事件的触发逻辑本质上是对齐的,自然也就没了效率优势。

怎么用代码验证?

如果你想亲手验证两者的效率,可以借助浏览器的performance API,或者DevTools的Performance面板:

1. 统计单次回调的执行耗时

let e = 0, r = 0;

new ResizeObserver(() => {
  const start = performance.now();
  console.log('resized from observer', r++);
  console.log('Observer 单次回调耗时:', performance.now() - start);
}).observe(document.documentElement);

window.addEventListener('resize', () => {
  const start = performance.now();
  console.log('resized from event', e++);
  console.log('Resize 事件单次回调耗时:', performance.now() - start);
});

快速拖动窗口resize,你会看到两者的单次回调耗时几乎完全一致,都是微秒级的差距,完全可以忽略。

2. 统计批量触发的总开销

如果想测试大量触发时的整体表现,可以加个计时结束的逻辑:

let eCount = 0, rCount = 0;
let eTotalTime = 0, rTotalTime = 0;
let testEnded = false;

// 监听ResizeObserver
new ResizeObserver(() => {
  if (testEnded) return;
  const start = performance.now();
  // 这里替换成你的无布局操作(比如只是计数)
  rCount++;
  rTotalTime += performance.now() - start;
}).observe(document.documentElement);

// 监听window resize事件
window.addEventListener('resize', () => {
  if (testEnded) return;
  const start = performance.now();
  // 同样的无布局操作
  eCount++;
  eTotalTime += performance.now() - start;
});

// 3秒后结束测试,打印统计结果
setTimeout(() => {
  testEnded = true;
  console.log(`ResizeObserver 总回调次数: ${rCount},总耗时: ${rTotalTime.toFixed(2)}ms`);
  console.log(`Window resize 总回调次数: ${eCount},总耗时: ${eTotalTime.toFixed(2)}ms`);
  console.log(`单次回调平均耗时 - Observer: ${(rTotalTime/rCount).toFixed(4)}ms,Event: ${(eTotalTime/eCount).toFixed(4)}ms`);
}, 3000);

快速拖动窗口3秒后,你会发现两者的总耗时、平均单次耗时几乎没有区别。

3. 用Chrome DevTools可视化验证

打开Chrome DevTools的「Performance」面板,点击录制按钮后快速拖动窗口resize,录制结束后查看:

  • 你会看到两者的回调函数在主线程上的占用时间几乎重合
  • 没有任何额外的布局、重绘开销(因为你的回调里没有布局读写)
  • 整体主线程占用率也没有明显差异

最后总结

在你这种无布局重计算的场景下,ResizeObserver和window resize事件监听器的效率是完全等价的。ResizeObserver的优势只体现在监听普通DOM元素尺寸变化的场景中,当监听根元素时,它和window resize事件的表现就没什么区别了。

备注:内容来源于stack exchange,提问作者Gaurang Tandon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.15 10:39:31