最稳妥方案是用Date对象配合setInterval每秒更新,需放脚本于</body>前或监听DOMContentLoaded,用textContent而非innerHTML,设间隔1000ms,并在页面隐藏时通过visibilitychange停用定时器。

直接用 Date 对象 + setInterval 每秒更新是最稳妥、兼容性最好的方案。其他方法要么有兼容风险,要么在页面隐藏时继续跑定时器浪费资源。
用 setInterval 实现每秒刷新
这是最主流、浏览器支持最全的做法,适合绝大多数静态页面或管理后台页眉时间显示。
- 必须把脚本放在
</body>前,或监听DOMContentLoaded,否则document.getElementById可能找不到元素 - 别用
innerHTML写纯时间字符串——改用textContent,避免意外解析 HTML 标签(比如时间里混入<符号会出错) - 间隔设成
1000毫秒即可,不必更短;设成500或100不仅没意义,还会增加主线程负担 - 示例代码片段:
function updateClock() {<br> const now = new Date();<br> const timeStr = now.toLocaleTimeString("zh-CN", { hour12: false });<br> document.getElementById("clock").textContent = timeStr;<br>}<br>setInterval(updateClock, 1000);<br>updateClock(); // 立即执行一次,避免首屏空白
用 requestAnimationFrame 替代 setInterval
只在需要“视觉更顺滑”或页面长时间运行(如监控大屏)时才考虑。它本身不保证每秒执行一次,只是在重绘前调用——真正更新时机仍得靠判断秒数是否变化。
- 必须手动比对上一次的
getSeconds()值,否则会高频刷 DOM,反而更卡 - 页面切到后台标签页时,
requestAnimationFrame会被浏览器自动降频甚至暂停,这点比setInterval更省电 - IE10+ 支持,但旧 Android WebView 有兼容问题,生产环境建议加兜底逻辑
- 关键点:不是“替代 setInterval”,而是“按需更新 + 浏览器协同”
格式化时间时容易漏掉的细节
手动拼接年月日时分秒看似自由,但几个坑几乎必踩:
生成Claude风格的精美单页HTML汇报文件。当用户需要生成"汇报"、"周报"、"月报"、"项目进度"、"复盘"、"演示"、"slide deck"、"状态报告"、"工作总结"时触发。支持6种模板:周报(weekly)、项目进度(project)、月度总结(monthly)、复盘报告(postmortem)、演示文稿(slid
立即学习“前端免费学习笔记(深入)”;
-
getMonth()返回的是0–11,不加+1就会显示 “2026年07月…” —— 这个错在开发机上看不出来,一上线就露馅 - 个位数补零不能只靠
String(n).padStart(2, "0"),某些老浏览器(如 iOS 9 Safari)不支持padStart,得用n < 10 ? "0" + n : n - 用
toLocaleTimeString()时传错语言标签(比如写成"zh"而非"zh-CN"),部分浏览器会回退到英文,导致中文用户看到 “PM” - 如果要显示星期几,
getDay()返回的是0–6(周日到周六),数组索引容易偏移 1 位
页面隐藏时要不要停掉定时器?
要停,而且必须停。不然标签页切走后,setInterval 仍在后台跑,既耗电又可能干扰其他逻辑(比如你用这个时间做倒计时,页面不可见时还在减)。
- 监听
visibilitychange事件,在document.hidden === true时调用clearInterval - 切回来时重新启动,但注意别重复
setInterval—— 建议把 timer ID 存成变量,每次启动前先clearInterval一下 -
requestAnimationFrame方案天然规避这个问题,但如果你混合用了两种方式,就得统一管理生命周期
真正难的不是让时间动起来,而是让时间在各种边界条件下都稳住:页面切后台、用户改系统时间、低性能设备卡顿、旧浏览器兼容……这些地方一漏,用户看到的就是跳秒、错月、乱码星期。


















