应只创建一次 date 实例获取所有时间字段,用 textcontent 更新 dom;setinterval 会因主线程阻塞而漂移,需时间戳校准;避免在 dom 加载前执行脚本。

用 setInterval 每秒更新,但别直接写字符串拼接
最常见做法是 setInterval(updateTime, 1000),但关键在 updateTime 函数里怎么取时间。别用 new Date().getHours() + ':' + new Date().getMinutes() 这种——每次调用都新建 Date 实例,两毫秒差就可能让分秒不一致(比如取到 12:59:59 的小时和 13:00:00 的分钟)。应该只调用一次 new Date(),再从它身上取所有字段:
function updateTime() {
const now = new Date(); // ← 只这里 new 一次
const h = String(now.getHours()).padStart(2, '0');
const m = String(now.getMinutes()).padStart(2, '0');
const s = String(now.getSeconds()).padStart(2, '0');
document.getElementById('clock').textContent = `${h}:${m}:${s}`;
}
用 textContent 而不是 innerHTML,避免意外解析 HTML 字符,也更快。
为什么 setInterval(fn, 1000) 会漂移?
JS 定时器不保证准时:主线程卡顿时,回调会被推迟;连续延迟几轮后,你看到的可能是 “12:26:58 → 12:27:00” 直接跳两秒。这不是 bug,是机制限制。如果你需要视觉上严格对齐秒变化(比如做直播倒计时),得靠时间戳校准:
- 启动时记下目标结束时间戳:
const target = Date.now() + 1000 - 每次回调里算剩余:
const remaining = Math.max(0, Math.ceil((target - Date.now()) / 1000)) - 只在
remaining变化时才更新 DOM,避免无效渲染
普通页面时钟不用这么重,但一旦发现秒数“跳变”或“卡住”,先怀疑是不是定时器堆积或主线程太忙。
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
requestAnimationFrame 不适合纯秒级更新
有人听说 requestAnimationFrame 更“流畅”,就拿来刷新时钟——这反而容易出问题。它每帧触发(通常 60fps),但秒数变化是离散事件,每秒最多更新 1 次。盲目用它会导致:
- 无意义高频调用(60 次/秒取时间,但只在秒变时才写 DOM)
- 如果没加节流判断,可能一秒内多次写同一值,浪费性能
- 代码逻辑变复杂:得自己比对上一次秒数,再决定是否更新
真要用 requestAnimationFrame,必须配合 now.getSeconds() 变化检测,否则不如老老实实用 setInterval。
DOM 元素还没加载完就执行脚本?
把 <script></script> 放在 里,又没加保护,document.getElementById('clock') 会返回 null,后续报错:Cannot set property 'textContent' of null。解决方式只有两个:
- 把
<script></script>标签移到前(最简单) - 或者用
DOMContentLoaded包一层:document.addEventListener('DOMContentLoaded', () => { setInterval(updateTime, 1000); });
别信“放 head 里加 window.onload 就行”——它等所有资源(图片、字体)加载完才触发,用户可能白等好几秒才看到时间。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










