使用事件侦听器发送数据

Azm*_*sov 5 javascript events

我有一个困境:我想用事件监听器发送一些数据,但也能够删除监听器.这是标准的封闭方法......

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属性来保存事件数据.

gbl*_*zex 3

考虑到您使用addEventListener不是问题,因为所有现代垃圾收集器都可以处理这种情况。事件监听器的问题仅存在于 IE 的实现中 (7-)。

测试- 10 000 个 addEventListener 和删除元素(请参阅 Windows 任务管理器)

当 DOM 对象包含对 JavaScript 对象(例如事件处理函数)的引用时,并且当该 JavaScript 对象包含对该 DOM 对象的引用时,就会形成循环结构。这本身并不是问题。当没有其他对 DOM 对象和事件处理程序的引用时,垃圾收集器(自动内存资源管理器)将回收 它们,从而允许重新分配它们的空间。JavaScript 垃圾收集器了解循环并且不会被它们混淆。

http://www.crockford.com/javascript/memory/leak.html