Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does a javascript event handler exist in memory even after the DOM element to which it is bound is removed?

Given the following code

<div id="app">
  <div id="foo" />
</div>

<script>
  $('#foo').bind('click', function(){});
</script>

I plan on replacing the contents of #app [e.g. $('#app').html('...');, or innerHTML = '...';]. I know that I can use jQuery's .remove() which calls a 'destroy' handler that unbinds events. The fact that there is a destroy handler set up to remove events leads me to believe that without unbinding the events, when the DOM element is removed, the handler will still exist in memory.

So, if the DOM element #foo no longer exists, does the handler disappear as well, or does it get lost in browser memory?

like image 973
Kappers Avatar asked May 03 '11 20:05

Kappers


People also ask

Are event listeners removed when element is removed?

According to the jquery Documentation when using remove() method over an element, all event listeners are removed from memory. This affects the element it selft and all child nodes. If you want to keep the event listners in memory you should use . detach() instead.

Does DOM use event handlers?

DOM elements can have functions hook onto events. The functions are called event handlers and the DOM element is known as an event target. The example code block shows how to register a function as an event handler.

What is event handling in DOM?

One of the keys to creating dynamic web pages is the use of event handlers. These allow you to execute specific script code in response to user or system initiated actions. Most events relate to the browser GUI, such as mouse movements, button or key clicks and updates to form inputs.


2 Answers

jQuery keeps track of event handlers itself, which is part of why you need to use unbind (nowadays it's off) if you're removing the element from the DOM not through a jQuery method (if you use jQuery's empty or remove, as you mentioned it handles this itself inernally). This is so jQuery knows it can release its reference to the handler.

If it weren't for that, then in theory, you wouldn't have to do anything because once the DOM element is removed from memory, it's no longer reachable, and so in theory shouldn't keep the event handler in memory. That's the theory. The reality is very different, it can be very easy to end up with a situation (particularly on IE) where neither the DOM element nor the event handler can get cleaned up because they're each causing the other to stick around — a memory leak. JavaScript has no issue with circular references (it understands them and can release two things that are pointing to each other as long as nothing else is pointing to them), but the DOM part of the browser is likely to be written in a different language with a different garbage collection mechanism (IE uses COM, which uses reference counting rather than reachability). jQuery helps you avoid this pitfall with IE (part of why it keeps track of event handlers), but you have to use unbind (nowadays off) (or remove elements via empty, remove, etc.) as a consequence.

The take away message: As you hook, so shall you unhook. :-) (And/or use jQuery when removing elements, since it will handle this.)

Somewhat related: If you're adding and removing elements a lot, you might look to see if event delegation (which jQuery makes really easy via the delegation signatures for on) might help.

like image 68
T.J. Crowder Avatar answered Oct 26 '22 07:10

T.J. Crowder


Just happened to read the docs on jQuery's empty() method:

To avoid memory leaks, jQuery removes other constructs such as data and event handlers from the child elements before removing the elements themselves.

like image 36
Kappers Avatar answered Oct 26 '22 06:10

Kappers