如何移除循环中创建的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
相关产品推荐
相关产品推荐

