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