(Note: I'm using jQuery below, but the question is really a general Javascript one.)
Say I've got a div#formsection
whose contents are repeatedly updated using AJAX, like this:
var formSection = $('div#formsection'); var newContents = $.get(/* URL for next section */); formSection.html(newContents);
Whenever I update this div, I trigger a custom event, which binds event handlers to some of the newly-added elements, like this:
// When the first section of the form is loaded, this runs... formSection.find('select#phonenumber').change(function(){/* stuff */}); ... // ... when the second section of the form is loaded, this runs... formSection.find('input#foo').focus(function(){/* stuff */});
So: I'm binding event handlers to some DOM nodes, then later, deleting those DOM nodes and inserting new ones (html()
does that) and binding event handlers to the new DOM nodes.
Are my event handlers deleted along with the DOM nodes they're bound to? In other words, as I load new sections, are lots of useless event handlers piling up in the browser memory, waiting for events on DOM nodes that no longer exist, or are they cleared out when their DOM nodes are deleted?
Bonus question: how can test this myself?
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.
❮ Previous Next ❯ HTML DOM events allow JavaScript to register different event handlers on elements in an HTML document. Events are normally used in combination with functions, and the function will not be executed before the event occurs (such as when a user clicks a button).
Event handler functions are subject to the same Garbage Collection that other variables are. That means they will be removed from memory when the interpreter determines that there is no possible means to obtain a reference to the function. Simply deleting a node however does not guarantee garbage collection. For instance, take this node and associated event handler
var node = document.getElementById('test'); node.onclick = function() { alert('hai') };
Now lets remove the node from the DOM
node.parentNode.removeChild(node);
So node
will no longer be visible on your website, but it clearly still exists in memory, as does the event handler
node.onclick(); //alerts hai
As long as the reference to node
is still accessible somehow, it's associated properties (of which onclick
is one) will remain intact.
Now let's try it without creating a dangling variable
document.getElementById('test').onclick = function() { alert('hai'); } document.getElementById('test').parentNode.removeChild(document.getElementById('test'));
In this case, there seems to be no further way to access the DOM node #test, so when a garbage collection cycle is run, the onclick
handler should be removed from memory.
But this is a very simple case. Javascript's use of closures can greatly complicate the determination of garbage collectability. Lets try binding a slightly more complex event handler function to onclick
document.getElementById('test').onclick = function() { var i = 0; setInterval(function() { console.log(i++); }, 1000); this.parentNode.removeChild(this); };
So when you click on #test, the element will instantly be removed, however one second later, and every second afterwards, you will see an incremented number printed to your console. The node is removed, and no further reference to it is possible, yet it seems parts of it remain. In this case the event handler function itself is likely not retained in memory but the scope it created is.
So the answer I guess is; it depends. If there are dangling, accessible references to deleted DOM nodes, their associated event handlers will still reside in memory, along with the rest of their properties. Even if this is not the case, the scope created by the event handler functions might still be in use and in memory.
In most cases (and happily ignoring IE6) it is best to just trust the Garbage Collector to do its job, Javascript is not C after all. However, in cases like the last example, it is important to write destructor functions of some sort to implicitly shut down functionality.
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