setTimeout只执行一次,setInterval反复执行直至手动清除;前者是延迟一次的宏任务,后者是按间隔触发但易堆积回调,误用会导致内存泄漏或UI卡顿。

setTimeout 只执行一次,setInterval 会反复执行,直到被手动清除。 这不是语义差别,而是底层行为和调度逻辑的根本不同——选错就可能造成内存泄漏、回调堆积或 UI 卡顿。
setTimeout 是「延迟触发一次」的宏任务
它把回调函数推入宏任务队列,等待至少指定毫秒后执行,且只执行一回。即使主线程卡住(比如跑了个 200ms 的 for 循环),实际执行时间也会被推迟,但不会补发。
- 最小延迟受浏览器限制,通常不低于
4ms(即使写0) - 返回一个数字 ID,必须用
clearTimeout(id)才能取消 - 参数支持传参:
setTimeout(greet, 1000, "Alice"),比拼字符串更安全 - 常见误用:在循环里反复创建却忘记存 ID 或 clearTimeout → 内存泄漏
let timer = setTimeout(() => {
console.log("只出现一次");
}, 1000);
// 后续想取消?得保留 timer 变量并调用:
// clearTimeout(timer);
setInterval 是「按表打卡」但不保准时钟精度
它尝试每 delay 毫秒执行一次回调,但前提是上一次回调已结束。如果回调耗时 > delay(比如接口慢、渲染重),下一次就会立刻执行,形成“回调堆积”,看起来像“突然连刷好几条”。
- 不会自动停止,必须显式调用
clearInterval(id) - 容易忽略清理:组件卸载、页面跳转后定时器还在跑 → 典型内存泄漏源
- 想实现真正稳定的间隔(如每秒刷新倒计时),推荐用
setTimeout递归代替
let count = 0;
const interval = setInterval(() => {
count++;
console.log(`第 ${count} 次`);
if (count >= 3) clearInterval(interval); // 必须主动停
}, 1000);
什么时候该用哪个?看任务是否需要「自我延续」
不是“重复就用 setInterval”,而是看逻辑是否天然具备终止条件或是否允许误差累积。
立即学习“Java免费学习笔记(深入)”;
- 防抖(debounce):用
setTimeout+clearTimeout,每次新输入就重置计时器 - 倒计时显示:用
setTimeout递归(setTimeout(fn, 1000)里再调自己),避免 setInterval 堆积导致跳秒 - 心跳检测 / 轮询:用
setInterval更直观,但务必加超时控制和错误兜底(比如连续失败 3 次就停) - DOM 渲染后操作:用
setTimeout(fn, 0),靠它把任务塞进下一个宏任务,确保 DOM 已更新
最常被忽略的一点:setInterval 的“间隔”是两次 开始执行 的时间差,不是两次 执行完成 的间隔。一旦回调变慢,整个节奏就崩了——这不是 bug,是设计使然。真要稳,就别贪方便,老实用 setTimeout 串起来。











