requestAnimationFrame 更适合 JavaScript 动画,因其对齐屏幕刷新节奏、自动适配设备刷新率、后台暂停节能,且动画更顺滑精准;而 setTimeout 仅尽力执行,易受线程阻塞影响,导致帧率不稳。

requestAnimationFrame 比 setTimeout 更适合做 JavaScript 动画,核心原因在于它专为动画而生:浏览器会自动把回调对齐到屏幕刷新节奏(通常是 60Hz),避免丢帧、卡顿和不必要的计算,还能在页面不可见时暂停执行,节省资源。
为什么 requestAnimationFrame 更精准
现代显示器大多以 60 帧/秒(约每 16.67ms 刷新一次)工作。setTimeout 只是“尽力”按设定时间执行,但受 JS 单线程、任务队列延迟、系统负载等影响,实际间隔可能偏差很大(比如设了 16ms,结果执行间隔是 12ms 或 24ms),导致动画忽快忽慢。
requestAnimationFrame 则由浏览器统一调度:它会在下一次屏幕绘制前触发回调,确保每次更新都赶在刷新点上,视觉更顺滑。
自动适配刷新率与节能
requestAnimationFrame 会根据设备真实刷新率调整调用频率(比如 iPad Pro 支持 120Hz,它就会以 ~8.3ms 调用);同时当标签页切换到后台或动画元素不可见时,浏览器通常会暂停调用,不白费 CPU 和电量。
立即学习“Java免费学习笔记(深入)”;
setTimeout 不具备这种感知能力,即使页面隐藏,只要定时器没被清除,它仍会不断触发,浪费性能。
写法更简洁,逻辑更清晰
实现一个简单的移动动画:
- 用 setTimeout 需手动控制循环、计算已过时间、处理暂停/恢复、防抖叠加等问题;
- 用 requestAnimationFrame 只需递归调用自身,配合 performance.now() 计算 Delta 时间,就能做出时间无关的平滑动画。
示例片段:
function animate() {
const now = performance.now();
const delta = now - lastTime;
// 更新位置:position += speed * (delta / 1000)
lastTime = now;
element.style.transform = `translateX(${position}px)`;
requestAnimationFrame(animate); // 下一帧继续
}
requestAnimationFrame(animate);
不是所有场景都要换
如果只是做倒计时、轮询接口、延时提示这类**和视觉刷新无关**的任务,setTimeout/setInterval 依然合适,也更直观;强行套用 requestAnimationFrame 反而可能因页面失焦导致计时不准确。
简单记:要改 DOM、画 Canvas、驱动 CSS 动画 → 优先 requestAnimationFrame;要按真实时间做逻辑调度 → 看需求选 setTimeout 或 Web Workers。











