Garbage collection of unneeded event listeners in javascript Garbage collection of unneeded event listeners in javascript google-chrome google-chrome

Garbage collection of unneeded event listeners in javascript


While jQuery is very good at removing event listeners to DOM elements that are removed via it's methods (including .html() - just read the API: http://api.jquery.com/html/) - it won't remove event listeners to DOM elements that may still have a reference to them in a detached DOM tree.

For example, if you do something like this:

$.ajax({    ....})    .done(function(response,status,jqXHR) {        //create a detached DOM tree        form = $(response)        //add an event listener to the detached tree        form.find('#someIDInTheResponse').on('submit',function() {        });        //add the form to the html        $('#someID').html(form);    });//at some other point in the code$('#someIDInTheResponse').remove();

Note that in the above example, despite the fact that you removed the element from the DOM, the listener will not be removed from memory. This is because the element still exists in memory in a detached DOM tree accessible via the global variable "form" (this is because I didn't create use "var" to create the initial detached DOM tree in the scope of the done function....there are some nuances and jQuery can't fix bad code, it can only do it's best.

2 other things:

Doing everything inside callbacks or event listeners (like do this on a button click) turns into real bad spaghetti code really fast and becomes unmanageable rather quickly. Try and separate application logic from UI interaction. For example, don't use callbacks to click events to perform a bunch of logic, use callbacks to click events to call functions that perform a bunch of logic.

Second, and somewhat less important, (I welcome feedback on this perspective via comments) I would deem 30MB of memory to be a fairly high baseline for a web app. I've got a pretty intensive google maps web app that hits 30MB after an hour or so of intensive use and you can really notice start to notice it's sluggishness when you do. Lord knows what it would act like if it ever hit 60MB. I'm thinking IE<9 would become virtually unusable at this point, although, like I said, I welcome other people's feedback on this idea.


I wonder if you are simply not unbinding/removing the previously bound event listeners when you replace fragments?

I briefly looked at the specific sections of code you linked to in your updated question, but didn't see any event listener binding other than what you are doing in document ready, so I'm guessing you are doing some additional binding when you replace the document fragments. I'm not a jQuery expert, but in general binding or assigning additional event listeners does not replace previously bound/assigned event listeners automatically.

My point is that you should look to see if you are doing binding via "click()" (or via some other approach) to existing elements without unbinding the existing event listener first.

You might take a look at moff's answer to this question, which provides an example for click, specifically.


I can't add a comment because of reputation but to respond to what Adam is saying...

To summarise the case Adam presents, it's potentially nothing to do with jQuery, the problem may be within normal Javascript. However you don't present enough code for anyone to really get to the bottom of the problem. Your usage of scoped encapsulation may be perfectly fine and the problem may be else where.

I would recommend that you search for tools for finding the cause of memory leaks (for example, visualising/traversing the entire object/scope/reference/function tree, etc).

One thing to watch out for with jQuery are plugins and global insertions into the DOM! I've seen many JS libs, not just jQuery plugins, fail to provide destroyers and cleanup methods. The worst offenders are often things with popups and popouts such as date pickers, dialogs, etc that have a nasty habit of appending layer divs and the like into body without removing them after.

Something to keep in mind if that a lot of people just get as far as to make things construct but don't handle destruct especially in JS because they expect still even in this day and age that you will be serving normal webpages. You should also check plugins for destroy methods because not all will hook onto a remove event. Events are also used in a messy fashion in jQuery by others so a rogue handler might be halting the execution of following cleanup events.

In summary, jQuery is a nice robust library but be warned, just because someone depends on it does not mean it inherits jQuery's quality.

Out of curiosity... have you checked the listeners on document.ready? Maybe you need to manually GC those.