← 返回目录

14. 定时器叠加与内存泄漏专项

两大高频 Bug:① 叠加——每次点击都 new 一个定时器,等于雇了 N 个人同时干活,转速失控;② 内存泄漏——弹窗关了、页面走了,定时器还在后台跑,内存越吃越多。规范:开新定时器前先清旧的;销毁前必清

14.1 互动演示(错误版 vs 修复版 对比)

错误版(叠加): 修复版(先清再设):
0
左按钮每次点击新增一个定时器(速度越来越快=叠加);右按钮先清除旧定时器(速度恒定=正常)。

14.2 知识点讲解

① 定时器叠加(重复创建)

点一次按钮创建一个定时器本来没问题,但每次都不清旧的、又开新的,多个定时器同时跑 → 回调被反复执行 → 数字跳得越来越快、逻辑错乱。

// 错误示范:点一下就新开一个,从不关旧的
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 之后输出停了 = 修好了
一句话记住:开新定时器前先 clearInterval 旧的(防叠加);弹窗关闭/页面卸载时清掉所有定时器(防泄漏)