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?
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.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With