setInterval中调用removeEventListener无法移除旧事件监听问题
根本原因
removeEventListener 移除监听器的必要前提是:传入的处理函数、事件名、配置参数(这里是捕获阶段true)必须和当初调用addEventListener绑定时的参数完全一致,其中处理函数必须是同一个引用,不能是逻辑相同但重新创建的不同函数。
你现在的代码里,每次tt被setInterval触发执行时,都会在函数内部重新创建一个全新的qq函数,传给removeEventListener的这个新qq和上一次间隔绑定上去的旧qq根本不是同一个引用,自然没法移除旧监听器,只会不断往document上叠加新的mouseup监听。
问题复现代码
let tt = function() { let qq = function() { console.log(1)} // 此处qq是本次执行新建的函数,和历史绑定的处理函数引用不一致,移除无效 document.removeEventListener('mouseup', qq, true); document.addEventListener('mouseup', qq, true); } setInterval( tt, 100)
修复方案
把事件处理函数的声明挪到tt外层,保证整个流程中只创建一次处理函数,每次移除和新增拿到的都是同一个引用即可:
// 事件处理函数只在外层声明一次,固定引用 const mouseupHandler = function() { console.log(1) } const bindInterval = function() { document.removeEventListener('mouseup', mouseupHandler, true); document.addEventListener('mouseup', mouseupHandler, true); } setInterval(bindInterval, 100)
额外注意
- 你用来排查问题的
getEventListeners(document)是Chrome DevTools控制台专属的调试API,只能在开发者工具的控制台里调用,不能写进线上业务代码。 - 如果业务场景需要频繁更新事件触发逻辑,更推荐用事件委托的方式统一处理,不要高频重复绑定、移除监听器,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Евгений Гедройц
相关产品推荐
相关产品推荐

