最简单可靠的方案是用 setInterval 每秒调用 new Date() 并用 textContent 更新 DOM;避免 innerHTML 防 XSS 且性能更好;定时器不精准但够用,需校验元素存在性并考虑页面可见性影响。

直接用 setInterval 每秒调用 new Date() 并更新 DOM 是最简单、兼容性最好、也最不容易出错的方案。别一上来就搞 requestAnimationFrame 或 Canvas,90% 的页面根本不需要那么重。
为什么不用 innerHTML 写时间?
写纯文本时间时,textContent 比 innerHTML 更安全、更快:
- 避免意外解析 HTML 字符(比如时间里混入
<或&会触发 XSS 风险) - 跳过 HTML 解析流程,DOM 更新开销更小
- 浏览器对纯文本写入做了优化,尤其在频繁更新场景下更稳
示例写法:document.getElementById('clock').textContent = now.toLocaleTimeString();
setInterval 的间隔设成 1000ms 真的准吗?
不准,但够用。浏览器主线程卡住时,setInterval 可能延迟执行,甚至“连发”补帧。不过对显示“时:分:秒”这种秒级精度需求完全没问题:
立即学习“前端免费学习笔记(深入)”;
- 用户肉眼无法分辨 100ms 左右的跳变
- 每次更新都取当前真实时间(不是靠计数器推算),不会累积误差
- 如果真需要毫秒级同步(比如倒计时归零动画),才该考虑
requestAnimationFrame+ 时间戳比对
别为了“理论上更准”加一堆判断逻辑,反而让代码难维护。
格式化时间时,padStart(2, '0') 和 toLocaleTimeString() 怎么选?
看需求场景:
- 要中文本地化(如“上午10:30:25”或“2026年8月26日 星期三”)→ 用
toLocaleTimeString()或toLocaleString(),传{ locale: 'zh-CN' }和选项对象 - 要固定格式(如
HH:mm:ss或YYYY-MM-DD HH:mm:ss)→ 手动取值 +padStart(2, '0'),可控性强,不依赖系统设置 - 要 ISO 格式(如存入
datetime属性)→ 直接用now.toISOString(),别自己拼
注意:getMonth() 返回 0–11,必须加 1;getDay() 是星期几(0=周日),不是日期,别弄混。
页面切到后台后,时间还在跑吗?
会跑,但浏览器通常会节流 setInterval,可能变成每秒甚至每几分钟才触发一次。这会导致时间显示明显滞后:
- 用户切回页面时,看到的是“跳了好几秒”的时间 解决办法是监听
- 更简单的做法:每次更新前先检查当前秒数是否变化,只在秒变时才写 DOM —— 这样即使定时器没停,也不会造成视觉跳变
visibilitychange 事件,在页面隐藏时暂停定时器,显示时立即重取时间并重启
真正容易被忽略的是:没做 DOM 元素存在性校验。如果脚本执行时 getElementById 找不到目标元素,后续所有更新都会静默失败,时间永远不出现。



















