You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确清除赋值给全局变量的setInterval定时器?

问题根源

你的代码clearInterval不生效是两个核心问题叠加导致的:

  • 定时器ID丢失:你用var声明的intervalCursor不是全局变量,作用域被限制在MutationObserver的回调函数内。更致命的是,每次类名变化、满足进入if分支的条件时,都会重新执行setInterval生成新的定时器,新ID会直接覆盖变量里存储的旧ID,之前创建的定时器ID彻底丢失,后续调用clearInterval只能清除最后一次生成的定时器,更早创建的定时器因为没有留存ID,根本无法被清除,会持续在后台运行。
  • 缺少重复初始化校验:每次进入if分支都会给window绑定一个新的mousemove事件监听,从未做解绑处理,触发几次符合条件的类名变更,就会绑定多少个重复的监听,既浪费性能,也会干扰坐标值的更新。另外你在update方法里直接给l、t赋值没有加变量声明,这两个值会泄漏成全局变量,也属于代码隐患。
修复后的完整实现

把定时器ID、事件处理函数等状态值提到Observer外层作用域留存,每次进入初始化分支前先清理旧的定时器和事件监听,避免重复创建资源:

const runPreview = document.querySelector('.projects');
// 核心状态提到外层作用域,避免ID、事件引用丢失
let intervalCursor = null;
let mousemoveHandler = null;
let mouseX = window.innerWidth / 2;
let mouseY = window.innerHeight / 2;
let projectPreview = null;

// 工具函数全局定义,不用每次初始化重复声明
function lerp(start, end, amt) {
  return (1 - amt) * start + amt * end
}

new MutationObserver((mutations) => {
  if (mutations[0].attributeName === 'class') {
    console.log('Project list class changed');

    if ($('html').hasClass('no-touchevents') && $('.projects').hasClass('run-preview')) {
      // 进入分支先清理旧资源,避免重复生成定时器、重复绑定事件
      if (intervalCursor) clearInterval(intervalCursor);
      if (mousemoveHandler) $(window).off('mousemove', mousemoveHandler);

      // 初始化预览元素配置
      projectPreview = {
        el: $('.image-container'),
        x: window.innerWidth / 2,
        y: window.innerHeight / 2,
        w: 300,
        h: 300,
        update: function () {
          // 加变量声明,避免污染全局
          const l = this.x - this.w / 2;
          const t = this.y - this.h / 2;
          this.el.css({
            'transform': 'translate3d(' + l + 'px,' + t + 'px, 0)'
          });
        }
      }

      // 保存事件处理函数引用,方便后续解绑
      mousemoveHandler = function (e) {
        mouseX = e.clientX;
        mouseY = e.clientY;
      }
      $(window).on('mousemove', mousemoveHandler);

      // 动画帧逻辑
      function move() {
        projectPreview.x = lerp(projectPreview.x, mouseX, 0.1);
        projectPreview.y = lerp(projectPreview.y, mouseY, 0.1);
        projectPreview.update();
      }

      // 启动定时器,留存ID
      intervalCursor = setInterval(move, 1000 / 60);

    } else if (!$('.projects').hasClass('run-preview')) {
      // 退出分支时同步清理定时器、解绑事件
      if (intervalCursor) {
        clearInterval(intervalCursor);
        intervalCursor = null;
      }
      if (mousemoveHandler) {
        $(window).off('mousemove', mousemoveHandler);
        mousemoveHandler = null;
      }
    }
  }
}).observe(runPreview, { attributes: true });

内容的提问来源于stack exchange,提问作者Ira

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 18:06:25