用 requestAnimationFrame 替代 setInterval 更新时间最省资源,因其与浏览器刷新同步、后台自动暂停、避免空转;setInterval 每秒强制执行,无视页面可见性与渲染状态,引发多余计算和重排。

用 requestAnimationFrame 替代 setInterval 更新时间,是当前最省资源的方案。它不强制固定帧率,而是与浏览器刷新节奏同步,避免掉帧、卡顿和空转消耗。
为什么 setInterval(new Date().toLocaleTimeString(), 1000) 是错的
这种写法本身就有语法错误——setInterval 第一个参数必须是函数,不是执行结果;但更深层的问题在于:每秒强制触发一次,不管浏览器是否在渲染、标签页是否激活、甚至页面是否在视口内,都会持续计时和重绘。
- 后台标签页中,
setInterval仍会运行(部分浏览器会节流到最低 1s,但仍有开销) - 时间字符串每次生成都触发 DOM 重排(尤其用 innerHTML 更新时)
- 未做格式缓存,重复调用
toLocaleTimeString()产生多余对象和格式化开销
requestAnimationFrame + 时间差校准的实际写法
核心思路是:只在下一帧即将绘制时才更新时间,并用上一帧的时间戳推算真实秒级变化,避免依赖系统时钟抖动或定时器漂移。
示例代码:
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
立即学习“前端免费学习笔记(深入)”;
let lastTime = 0;
const timeEl = document.getElementById('clock');
<p>function updateClock(timestamp) {
// timestamp 是高精度时间戳(毫秒),比 Date.now() 更稳定
if (timestamp - lastTime >= 950) { // 允许 ±50ms 容错,防抖
const now = new Date();
timeEl.textContent = now.toLocaleTimeString('zh-CN', {
hour12: false,
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
});
lastTime = timestamp;
}
requestAnimationFrame(updateClock);
}</p><p>requestAnimationFrame(updateClock);
- 不依赖
setInterval,标签页切到后台时,requestAnimationFrame自动暂停 - 用
timestamp参数而非Date.now(),减少时间获取误差 - 加了 950ms 判断,防止因帧率波动导致跳秒或重复渲染
DOM 更新前先判断是否真有变化
即使时间变了,如果只是秒数递增而显示格式没变(比如从 "13:09:05" 到 "13:09:06"),也不必触发文本重设。可缓存上一次格式化结果,做浅比较。
- 对纯数字时钟,可只更新
<span class="second">内容,其余不动 - 用
textContent而非innerHTML,避免 HTML 解析开销 - 若使用
<time>标签,记得同步更新datetime属性,保持语义正确
真正省资源的关键不在“怎么取时间”,而在于“什么时候取”和“要不要更新”。高频轮询、无差别重绘、未适配页面可见性,才是耗电和卡顿的主因。哪怕用了 Web Worker 处理时间计算,若 DOM 更新仍塞在主线程且不节制,照样拖慢页面。


















