使用箭头函数结合addEventListener时,如何移除事件监听器?
问题分析与解决方案
问题根源
- 无法移除监听器:每次调用
() => fu()都会生成一个全新的匿名函数,addEventListener和removeEventListener传入的不是同一个函数引用,自然无法移除绑定的事件。 - this指向异常:箭头函数没有独立的
this,它的this继承自外层作用域(此处是window.onresize的回调函数,其this指向window)。直接调用fu()时,fu作为普通函数执行,this默认指向window。
解决方案
根据需求分场景给出实现方式:
场景1:需要fu中的this指向divideBtn,同时正常移除监听器
方案A:使用bind绑定this并保存函数引用
const divideBtn = document.querySelector('.button--div'); function fu() { console.log('click'); console.log(this); // 指向divideBtn }; // 提前创建绑定好this的函数,复用同一个引用 const boundFu = fu.bind(divideBtn); // 标记是否已绑定事件,避免重复添加 let isEventBound = false; window.onresize = function () { const windowWidth = window.innerWidth; if (windowWidth >= 992 && !isEventBound) { divideBtn.addEventListener('click', boundFu); isEventBound = true; } else if (windowWidth < 992 && isEventBound) { divideBtn.removeEventListener('click', boundFu); isEventBound = false; } };
方案B:用箭头函数包裹并手动绑定this,同时保存引用
const divideBtn = document.querySelector('.button--div'); function fu() { console.log('click'); console.log(this); // 指向divideBtn }; // 提前定义箭头函数,复用同一个引用,同时用call绑定this const arrowWrappedFu = () => fu.call(divideBtn); let isEventBound = false; window.onresize = function () { const windowWidth = window.innerWidth; if (windowWidth >= 992 && !isEventBound) { divideBtn.addEventListener('click', arrowWrappedFu); isEventBound = true; } else if (windowWidth < 992 && isEventBound) { divideBtn.removeEventListener('click', arrowWrappedFu); isEventBound = false; } };
场景2:接受fu中的this指向window,仅解决移除问题
只需提前保存箭头函数的引用,避免每次创建新函数:
const divideBtn = document.querySelector('.button--div'); function fu() { console.log('click'); console.log(this); // 指向window }; // 提前保存箭头函数引用 const arrowFu = () => fu(); let isEventBound = false; window.onresize = function () { const windowWidth = window.innerWidth; if (windowWidth >= 992 && !isEventBound) { divideBtn.addEventListener('click', arrowFu); isEventBound = true; } else if (windowWidth < 992 && isEventBound) { divideBtn.removeEventListener('click', arrowFu); isEventBound = false; } };
内容的提问来源于stack exchange,提问作者Marcin
相关产品推荐
相关产品推荐

