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

如何移除循环中创建的JavaScript事件监听器

解决方案

问题根源在于每次调用_setUpEventHandlers时,循环内通过bind创建的onClickFunction都是全新的函数引用——bind方法每次调用都会返回一个新函数,所以第二次调用时用新函数执行removeEventListener,根本匹配不上第一次添加的监听器,自然无法移除。

要解决这个问题,核心是在类实例中保存每一个元素对应的事件处理函数引用,这样下次移除时能精准找到同一个函数。

修改后的代码实现

class myClass {
    constructor(input_foo) {
        this.foo = input_foo;
        // 新增:维护元素与对应事件处理函数的映射
        this.eventHandlers = new Map();
        
        this._setUpEventHandlers();
        this._setUpEventHandlers(); // 现在第二次调用会正确移除第一次的监听器
    };

    _setUpEventHandlers() {
        document.querySelectorAll('.click_me').forEach(element => {
            // 第一步:取出之前保存的处理函数,移除旧监听器
            const oldHandler = this.eventHandlers.get(element);
            if (oldHandler) {
                element.removeEventListener('click', oldHandler, false);
            }
            
            // 第二步:创建新的处理函数并绑定this
            const onClickFunction = function(event) {
                this.onClick(element, event);
            }.bind(this);
            
            // 第三步:添加新监听器,同时更新映射保存新函数
            element.addEventListener('click', onClickFunction, false);
            this.eventHandlers.set(element, onClickFunction);
        });
    }

    onClick(element, event) {
        event.preventDefault();
        console.log(this);
        console.log(event);
        console.log(element);
        console.log('<br>');
    }
}

关键改动说明

  • 新增this.eventHandlers = new Map():用Map存储元素和对应事件处理函数的映射,Map支持直接以DOM元素作为键,能精准对应每个元素的处理函数。
  • 在_setUpEventHandlers中,先从Map取出旧的处理函数,调用removeEventListener移除旧监听器。
  • 创建新的处理函数后,添加监听器的同时将新函数存入Map,覆盖旧引用,确保下次调用时能拿到最新的函数。

这样每次调用_setUpEventHandlers,都会先移除当前元素上绑定的旧监听器,再添加新的,不会出现监听器叠加的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 17:22:29