无法使用removeEventListener移除事件监听器的技术问题求助
问题原因
你遇到的核心问题是:Function.prototype.bind() 每次调用都会返回一个全新的函数实例。你绑定事件时用的是handleKeyDown.bind(this)生成的新函数,但移除时传入的是原handleKeyDown函数,两者引用不同,所以removeEventListener找不到对应的监听器,自然无法移除。而且每次触发绑定逻辑,都会新增一个独立的监听器,导致越积越多。
解决方法
方案1:提前保存绑定后的函数引用
在合适的作用域(比如类的实例属性、模块级变量)里存储绑定后的函数,后续添加和移除都用这个引用:
// 提前保存绑定后的函数(比如在类的构造函数或初始化逻辑里) this.boundHandleKeyDown = this.handleKeyDown.bind(this); // 添加监听器时用这个保存的引用 body.addEventListener('keydown', this.boundHandleKeyDown); // 在handleKeyDown里移除时同样用这个引用 handleKeyDown(e) { const workoutEdit = document.querySelector('.formEdit'); const backdrop = document.querySelector('.backdrop'); if (e.key === 'Escape' && workoutEdit && backdrop) { curWorkout.parentElement.removeChild(workoutEdit); curWorkout.parentElement.removeChild(backdrop); body.removeEventListener('keydown', this.boundHandleKeyDown); } if (e.key === 'Enter') { this.#workouts[indexWorkout].distance = +editDistance.value; this.#workouts[indexWorkout].duration = +editDuration.value; console.log(this.#workouts); body.removeEventListener('keydown', this.boundHandleKeyDown); } }
方案2:使用箭头函数作为回调(需保存引用)
如果你的环境支持箭头函数,也可以用箭头函数来保留this上下文,但同样要提前保存引用,避免每次生成新函数:
// 提前定义箭头函数(确保作用域正确) this.handleKeyDown = (e) => { const workoutEdit = document.querySelector('.formEdit'); const backdrop = document.querySelector('.backdrop'); if (e.key === 'Escape' && workoutEdit && backdrop) { curWorkout.parentElement.removeChild(workoutEdit); curWorkout.parentElement.removeChild(backdrop); body.removeEventListener('keydown', this.handleKeyDown); } if (e.key === 'Enter') { this.#workouts[indexWorkout].distance = +editDistance.value; this.#workouts[indexWorkout].duration = +editDuration.value; console.log(this.#workouts); body.removeEventListener('keydown', this.handleKeyDown); } }; // 添加监听器 body.addEventListener('keydown', this.handleKeyDown);
关键注意点
- 一定要保证添加和移除监听器时用的是同一个函数引用,这是
removeEventListener生效的核心前提。 - 如果是在类组件场景里,别在每次渲染逻辑里直接写
bind或箭头函数,否则会重复生成新函数,导致监听器越绑越多。
内容的提问来源于stack exchange,提问作者Piotr Ruszkiewicz
相关产品推荐
相关产品推荐

