JavaScript中removeEventListener无法生效的原因是什么?
问题:addEventListener正常工作,但removeEventListener无法生效?
我尝试使用以下代码添加或移除EventListener:
function a(input) { var b = document.getElementsByClassName("class_name"); if (input == "add"){ for (let i = 0; i < 5; i++){ b[i].addEventListener("click", c); // 这部分正常工作! } } if (input == "remove"){ for (let i = 0; i < 5; i++){ b[i].removeEventListener("click", c); // 这部分无法生效! } } function c(d){ random_function(e); // "e" 是全局变量 e = d.currentTarget.getAttribute("id"); random_function(e); // 再次调用同一函数 } }
其中addEventListener可正常工作,但removeEventListener无法生效,请问这是什么原因?
原因分析与解决方法
核心问题是每次调用函数a时,内部定义的c都是一个全新的函数实例。
因为函数c嵌套在a内部,每执行一次a,JavaScript就会创建一个完全独立的c函数。当你调用a("add")时,添加的是这次调用生成的c;而调用a("remove")时,试图移除的是另一次调用生成的新c——这两个c不是同一个引用,removeEventListener找不到匹配的事件处理函数,自然无法生效。
解决方法:确保添加和移除用的是同一个函数引用
有两种常见的处理方式:
把函数
c移到a的外部
让c成为外层作用域的独立函数,这样每次调用a时引用的都是同一个c实例:function c(d){ random_function(e); // "e" 是全局变量 e = d.currentTarget.getAttribute("id"); random_function(e); // 再次调用同一函数 } function a(input) { var b = document.getElementsByClassName("class_name"); if (input == "add"){ for (let i = 0; i < 5; i++){ b[i].addEventListener("click", c); } } if (input == "remove"){ for (let i = 0; i < 5; i++){ b[i].removeEventListener("click", c); } } }利用闭包保存
c的引用
如果不想暴露c到全局,可以用闭包在a的外层作用域保存c,确保每次调用a都复用同一个c:(function() { function c(d){ random_function(e); e = d.currentTarget.getAttribute("id"); random_function(e); } window.a = function(input) { var b = document.getElementsByClassName("class_name"); if (input == "add"){ for (let i = 0; i < 5; i++){ b[i].addEventListener("click", c); } } if (input == "remove"){ for (let i = 0; i < 5; i++){ b[i].removeEventListener("click", c); } } } })();
这样修改后,添加和移除事件时使用的是同一个函数引用,removeEventListener就能正常匹配并移除对应的事件处理函数了。
内容的提问来源于stack exchange,提问作者ziphackm
相关产品推荐
相关产品推荐

