Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sending data with an event listener

I have a predicament: I want to send some data with an event listener but also be able to remove the listener. Here's the standard closure approach...

var fn = function(e){method(e,data)};
el.addEventListener('click',fn,false);
el.removeEventListener('click',fn,false);

and you could remove the event, just fine. But say, the element was removed from the DOM? Then, you'd be left with the fn function sitting around. After removing a couple thousand DOM elements, it will result in something of a memory leak.

I've considered attaching a DOMNodeRemoved event handler, that would remove any left over functions/data along with the removed node. But apparently, that event isn't cross-browser compatible.

The only other option I've come up with would be modifying the element's DOM. Consider...

el.MyEventData = function(e){method(e,data)};
el.addEventListener('click',el.MyEventData,false);
el.removeEventListener('click',el.MyEventData,false);

Is modifying the DOM acceptable in this situation? The only sticky part of that solution is when you try to add more than one event listener. Let's say we made a custom function to parse the adding/removing of events...

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;
        }
    }
}

It still modifies the DOM, as before, and certainly isn't a very elegant solution either. Does anyone know of any alternative, better method for passing data?

EDIT: So, I've looked into a little of jQuery's data/event scripts. I don't completely understand the code, so if someone would clarify, it would be helpful. But it seems as though they use a similar method, by making some type of el.cache property, that holds event data.

like image 629
Azmisov Avatar asked Oct 12 '10 01:10

Azmisov


2 Answers

Considering that you use addEventListener this is not an issue as all modern garbage collectors can take care of such situations. The problem with event listeners only exists in IE's implementation (7-).

Test - 10 000 addEventListener and remove element (see Windows Task Manager)

When a DOM object contains a reference to a JavaScript object (such an event handling function), and when that JavaScript object contains a reference to that DOM object, then a cyclic structure is formed. This is not in itself a problem. At such time as there are no other references to the DOM object and the event handler, then the garbage collector (an automatic memory resource manager) will reclaim them both, allowing their space to be reallocated. The JavaScript garbage collector understands about cycles and is not confused by them.

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

like image 150
25 revs, 4 users 83% Avatar answered Sep 21 '22 16:09

25 revs, 4 users 83%


Did you consider .delegate()?

like image 40
Rimantas Avatar answered Sep 20 '22 16:09

Rimantas