定时器的坑:叠加执行、内存泄漏、this 丢失。
核心三个坑:
① 叠加——上一次还没执行完下一次又来了
② 内存泄漏——组件销毁了定时器还在跑
③ this 丢失——回调里 this 不是原来的对象
坑:切换页面要 clearInterval、用闭包或 bind 修 this、防抖节流解决叠加。
点一次按钮创建一个定时器本来没问题,但每次都不清旧的、又开新的,多个定时器同时跑 → 回调被反复执行 → 数字跳得越来越快、逻辑错乱。
// 错误示范:点一下就新开一个,从不关旧的
btn.onclick = function () {
setInterval(function () {
// 每点一次就多一个在跑
console.log("叠加 bug");
}, 1000);
};
// 连点 5 下 = 5 个定时器同时干活!数字疯跳
// 正确做法:开新的之前,先把旧的关掉
// 用变量把定时器编号记下来
let loopTimer = null;
btn.onclick = function () {
if (loopTimer) {
// 手上已经有一个了
// 先把旧的辞退
clearInterval(loopTimer);
}
loopTimer = setInterval(function () {
// 再招新的
console.log("正常循环");
}, 1000);
};
// 任何时候手上只留一个定时器,不会叠加
双重拦截最稳:① timer 变量判断(if(timer) return)+ ② 按钮 disabled——抽奖、抢购、搜索防抖都这么干(第 16 页实战会用到)。
// 为啥会"偷内存":
// 原因 1:页面切走了、弹窗关了、组件拆了,可你没清定时器
// → 它还在后台默默跑,白白占着内存
// 原因 2:定时器里还拽着页面上的 DOM、变量不放
// → 页面都没了,JS 引擎以为"还有人在用",不敢回收
// 怎么修:在关弹窗、关页面的时候,把定时器都清掉
closeBtn.addEventListener("click", function () {
// 清循环闹钟
clearInterval(loopTimer);
// 清单次闹钟
clearTimeout(delayTimer);
});
开发硬性规范:凡是循环定时器,必须配套清除逻辑;页面销毁、重复触发场景务必手动清空定时器 ID。
// 1. 按 F12 打开 Console,盯着看有没有"停不下来的输出" // 2. 把弹窗关了,等 2 秒再看 Console 是不是还在打印 // → 还在打 = 定时器没关干净,漏了 // 3. 在关闭事件里加了 clearInterval 之后输出停了 = 修好了
| API | 作用 | 参数 | 返回值 | 代码示例 |
|---|---|---|---|---|
| setInterval(函数, 毫秒) | 重复点会叠加,越跑越快 | 函数、毫秒 | ID | let t = setInterval(fn, 100); // 重复点会叠加 |
| clearTimeout(delayTimer) | 清单次闹钟(关弹窗/页面时一起清) | 定时器 ID | 无 | clearTimeout(delayTimer); // 关弹窗时清 |
| clearInterval(旧ID) | 重定前先把旧闹钟清掉 | 定时器 ID | 无 | clearInterval(oldId); // 重定前先清旧的 |
| 按钮.disabled = true | 跑起来就锁按钮,防连点 | true / false | 无 | btn.disabled = true; // 锁按钮防连点 |