setTimeout和setInterval在低功耗模式下变慢,因浏览器主动限制定时器精度;requestAnimationFrame被节流导致动画卡顿;需用performance.now()实测判断节流状态。

HTML 本身没有“函数”——卡顿和电源管理无关,真正受影响的是 JavaScript 执行、定时器精度和渲染管线。
为什么 setTimeout 和 setInterval 在低功耗模式下变慢
操作系统(如 Windows 电源计划为“省电”,macOS 启用“自动降低图形性能”,iOS 后台标签页)会主动限制浏览器的定时器精度。Chrome 和 Edge 默认将后台标签页的 setTimeout 最小间隔从 4ms 拉长到 1000ms;Safari 更激进,可能压到 10s 级别。
- 不是代码写错了,是浏览器主动降频——
setTimeout(fn, 16)实际可能 1000ms 后才触发 - 仅影响非活跃标签页或系统整体进入低功耗状态时,前台全屏页面通常不受限
- Web Workers 中的定时器同样受制于该策略,无法绕过
动画卡顿真凶:requestAnimationFrame 被节流
requestAnimationFrame 不是“每帧调用”,而是由浏览器决定是否调度。在低功耗/后台/电池电量低于 20% 时,Chrome 可能将其降为每秒 1–2 帧,导致 CSS 动画或 Canvas 渲染明显卡顿、跳帧。
- 检查方式:在 DevTools 的 Performance 面板中录制,看 FPS 曲线是否突然跌至个位数
- 无法通过
style.will-change: transform或transform: translateZ(0)强制提升 - 替代方案:对非关键动画改用 CSS
@keyframes+animation-play-state控制暂停,比 JS 驱动更稳
如何判断当前是否被节流?用 document.hidden 和 navigator.onLine 不够
document.hidden 只反映标签页可见性,navigator.onLine 只管网络,二者都不代表 CPU/渲染节流状态。真实节流需结合行为探测:
- 启动一个高精度时间戳循环:
let start = performance.now(); setTimeout(() => console.log(performance.now() - start), 100),若输出远大于 100(如 >500),大概率被节流 - 监听
pagehide/visibilitychange事件,在隐藏前保存状态,避免恢复时重绘压力突增 - 不要依赖
navigator.hardwareConcurrency判断——它返回逻辑核心数,和当前是否节流无关
最常被忽略的一点:即使用户插着电源,macOS 的“优化电池充电”或 Windows 的“快速启动”仍可能让系统在空闲时进入轻度节流状态,此时页面无报错、无警告,只有动画和轮询变慢——得靠实测时间戳才能确认。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











