views:

22

answers:

2

I want to understand how event binding/unbinding works in browsers. Specifically, if I remove an element that already has an event bound to it, using for example jQuery: $("#anElement").remove();, will the bound event get removed as well?

In other words, if I don't unbind() the event first, am I creating some sort of memory leak?

Edit: I know that a handler won't be triggered again if an element is removed and then added, but what happens to the handler? Does it still sit somewhere in the browser/DOM?

A: 

yes, you don't have to unbind. jQuery does that for you.

here's a simple demo.

$(function(){
    $('#featured').click(function(){
        alert('test');
    });
    var elem;
    $('#remove').click(function(){
       elem = $('#featured').remove();        
    });
    $('#attach').click(function(){
       elem.appendTo('body');        
    });
});
Reigel
Thanks Reigel. I understand that the event handler will no longer be triggered if you remove and add the element again, but the question is whether or not the browser will still keep the handler in memory (and check against it), even though it will never match? But if jQuery specifically unbinds events when you call remove() then that answers my question too.
box9
ahh yes, jQuery already done that for you. if you view [jQuery.js](http://code.jquery.com/jquery-1.4.2.js) and do a search of `memory leak`, you can see comments about that.
Reigel
A: 

When you call .remove() (or .empty()) the event handlers are removed, you're not leaking memory (at least not from this, or there's another bug in play).

Here's what happens (in current source):

remove: function( selector, keepData ) {
  for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
    if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {
      if ( !keepData && elem.nodeType === 1 ) {
        jQuery.cleanData( elem.getElementsByTagName("*") );
        jQuery.cleanData( [ elem ] );
      }

      if ( elem.parentNode ) {
         elem.parentNode.removeChild( elem );
      }
    }
  }
  return this;
}

The important part is this bit:

jQuery.cleanData( elem.getElementsByTagName("*") );
jQuery.cleanData( [ elem ] );

This runs cleanData() on any child elements and the elements itself, this removes the data and events it has from $.cache, which cleans up the memory they were using, and interally calls jQuery.event.remove() which cleans up the event handlers individually.

Nick Craver
Ah. So the events DO need to be removed explicitly (and don't die with the element), but jQuery handles it for you
box9