我有一个困境:我想用事件监听器发送一些数据,但也能够删除监听器.这是标准的封闭方法......
var fn = function(e){method(e,data)};
el.addEventListener('click',fn,false);
el.removeEventListener('click',fn,false);
Run Code Online (Sandbox Code Playgroud)
你可以删除这个事件,就好了.但是说,该元素已从DOM中删除?然后,你将被留下来的fn功能.删除几千个DOM元素后,会导致内存泄漏.
我已经考虑过附加一个DOMNodeRemoved事件处理程序,它会删除任何遗留的函数/数据以及被删除的节点.但显然,该事件不是跨浏览器兼容的.
我提出的唯一其他选择是修改元素的DOM.考虑...
el.MyEventData = function(e){method(e,data)};
el.addEventListener('click',el.MyEventData,false);
el.removeEventListener('click',el.MyEventData,false);
Run Code Online (Sandbox Code Playgroud)
在这种情况下修改DOM是否可接受?当您尝试添加多个事件侦听器时,该解决方案的唯一粘性部分.假设我们制作了一个自定义函数来解析事件的添加/删除......
function makeEvent(fn,data){
var dataFn = function(e){fn(e,data)};
//create object to hold all added events
el.myEvents = {};
//make ID for this specific event
var eventID = ranString();
//add the event to the events object
el.myEvents[eventID] = [fn,dataFn];
//finally add the listener
el.addEventListener('click',dataFn,false);
}
function destroyEvent(fn){
//find all fn references
for(var id in el.myEvents){
if (el.myEvents[id][0] == fn){
el.removeEventListener('click',el.myEvents[id][1],false);
el.myEvents[id] = null;
}
}
}
Run Code Online (Sandbox Code Playgroud)
它仍像以前一样修改DOM,当然也不是一个非常优雅的解决方案.有没有人知道任何替代,更好的传递数据的方法?
编辑:所以,我已经研究了一些jQuery的数据/事件脚本.我不完全理解代码,所以如果有人澄清,那将会有所帮助.但似乎他们使用类似的方法,通过制作某种类型的el.cache属性来保存事件数据.
考虑到您使用addEventListener它不是问题,因为所有现代垃圾收集器都可以处理这种情况。事件监听器的问题仅存在于 IE 的实现中 (7-)。
测试- 10 000 个 addEventListener 和删除元素(请参阅 Windows 任务管理器)
当 DOM 对象包含对 JavaScript 对象(例如事件处理函数)的引用时,并且当该 JavaScript 对象包含对该 DOM 对象的引用时,就会形成循环结构。这本身并不是问题。当没有其他对 DOM 对象和事件处理程序的引用时,垃圾收集器(自动内存资源管理器)将回收 它们,从而允许重新分配它们的空间。JavaScript 垃圾收集器了解循环并且不会被它们混淆。
http://www.crockford.com/javascript/memory/leak.html