推荐用 setInterval + new Date() + textContent + DOM 检查,脚本放 </body> 前或用 DOMContentLoaded;避免 innerHTML、eval 字符串、手动拼接日期;优先用 Intl.DateTimeFormat 和 toLocaleTimeString()(加 hour12: false)或 toISOString()。

直接用 setInterval 每秒更新,最简单也最容易出错
这不是“推荐不推荐”的问题,而是:只要没加防抖或 DOM 存在检查,setInterval 一启动就可能报 document.getElementById(...) is null。常见于把 <script> 放在 <head> 里,而目标元素还没加载。
实操建议:
- 把
<script>标签放在</body>前,或用DOMContentLoaded包裹初始化逻辑 - 别用
innerHTML写纯时间——有 XSS 风险且多一次 HTML 解析;改用textContent - 别写
setInterval("...", 1000)这种字符串形式,它会触发eval,现代浏览器已警告弃用 - 示例安全写法:
function updateClock() {<br> const el = document.getElementById("clock");<br> if (!el) return;<br> el.textContent = new Date().toLocaleTimeString("zh-CN", { hour12: false });<br>}<br>setInterval(updateClock, 1000);<br>updateClock(); // 立即执行一次,避免首屏空白
toLocaleTimeString() 和 toISOString() 选哪个?看用途
如果你只是在页眉显示“15:28:42”,用 toLocaleTimeString();如果这个时间要传给后端、做日志比对、或需要跨时区一致,必须用 toISOString()(返回 UTC 时间,带 Z 后缀)。
注意点:
立即学习“前端免费学习笔记(深入)”;
-
toLocaleTimeString()输出依赖用户本地系统设置,中文 Win10 默认是 “下午 3:28:42”,加{ hour12: false }才得 “15:28:42” -
toISOString()永远返回类似"2026-08-27T08:48:00.123Z"的格式,毫秒精度固定三位,且不含本地时区偏移 - 别试图用
toISOString().slice(11, 19)截取“时间部分”——它切出来的是 UTC 时间,不是用户看到的本地时间
为什么 requestAnimationFrame 不适合做时钟?
它常被误传为“更精准的替代方案”,但实际只在动画帧率敏感场景(如 canvas 动画)有意义。对时钟来说,它的刷新节奏由屏幕帧率决定(通常是 60fps),而你真正需要的是**按秒对齐**——哪怕页面卡住两秒,恢复后也该跳过中间秒数,而不是补帧。
真实问题:
- 如果用户切到其他 tab,
requestAnimationFrame会被浏览器节流甚至暂停,导致时间停滞 - 它无法保证每秒只触发一次;可能一帧内多次调用,也可能几秒不调用
- 正确做法仍是
setInterval+ 每次读取new Date(),靠时间戳本身对齐,而非依赖定时器精度
补零、月份+1、星期转中文——手动拼接前先确认是否真需要
很多人一上来就写 getMonth()+1、String(date.getDate()).padStart(2,'0'),结果发现 iOS Safari 对 padStart 兼容性差,或忘了 getMonth() 返回 0–11 导致 12 月显示成 13。
更稳的选择:
- 用
Intl.DateTimeFormat替代手动拼接,例如:const formatter = new Intl.DateTimeFormat("zh-CN", {<br> year: "numeric",<br> month: "2-digit",<br> day: "2-digit",<br> hour: "2-digit",<br> minute: "2-digit",<br> second: "2-digit",<br> hour12: false<br>});<br>formatter.format(new Date()) // → "2026-08-27 08:48:00" - 如果只需“年月日”,直接用
<time datetime="2026-08-27">今天</time>,语义清晰且无需 JS - 星期几用
toLocaleDateString("zh-CN", { weekday: "long" }),比查数组映射更可靠
setInterval 启动后用户关了页面标签,定时器还在跑;比如用了 toLocaleTimeString() 却没测过阿拉伯语系统下冒号变成 Unicode 分隔符……这些细节不验证,上线就是生产事故。



















