i am using jquery and doing something like this
DOM
:
<div id="parent"></div>
JS
:
var _doSomeThing = function()
{
//some codes
}
$(function()
{
// appending div and binding methods to span
$('#parent').append('<span>1</span>');
$('#parent').append('<span>2</span>');
$('#parent span').bind('click', _doSomeThing);
});
function _clearDiv()
{
//clear div
$('#parent').html('');
}
//sometime in future, call clear div
_clearDiv();
Now my question is, do binding events to DOM
and later just removing the elements from DOM
leads to memory leakage?
If yes, how to solve this problem?
The JavaScript engine allocates memory when you create objects and variables in your application, and it is smart enough to clear out the memory when you no longer need the objects. Memory leaks are caused due to flaws in your logic, and they make way for poor performance in your application.
Memory safe languages include Rust, Go, C#, Java, Swift, Python, and JavaScript. Languages that are not memory safe include C, C++, and assembly.
Open the Start menu, search for Advanced System Settings, and select the Best match. In the Variable name field enter NODE_OPTIONS. In the Variable value field enter --max-old-space-size=4096. This value will allocate 4GB of virtual memory to Node.
the jQuery html
method attempts to prevent memory leaks by removing event handlers for any elements that are deleted as a result of calling .html('')
on a jQuery object.
From the 1.4.2 source
html: function( value ) {
if ( value === undefined ) {
return this[0] && this[0].nodeType === 1 ?
this[0].innerHTML.replace(rinlinejQuery, "") :
null;
}
// See if we can take a shortcut and just use innerHTML
// THE RELEVANT PART
else if ( typeof value === "string" && !rnocache.test( value ) &&
(jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&
!wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) {
value = value.replace(rxhtmlTag, fcloseTag);
try {
for ( var i = 0, l = this.length; i < l; i++ ) {
// Remove element nodes and prevent memory leaks
if ( this[i].nodeType === 1 ) {
jQuery.cleanData( this[i].getElementsByTagName("*") );
this[i].innerHTML = value;
}
}
// If using innerHTML throws an exception, use the fallback method
}
catch(e) {
this.empty().append( value );
}
}
else if ( jQuery.isFunction( value ) ) {
this.each(function(i){
var self = jQuery(this), old = self.html();
self.empty().append(function(){
return value.call( this, i, old );
});
});
}
else {
this.empty().append( value );
}
return this;
}
We can see that the jQuery.cleanData()
function is called. Here is the source for that
cleanData: function( elems ) {
var data, id, cache = jQuery.cache,
special = jQuery.event.special,
deleteExpando = jQuery.support.deleteExpando;
for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
id = elem[ jQuery.expando ];
if ( id ) {
data = cache[ id ];
if ( data.events ) {
for ( var type in data.events ) {
if ( special[ type ] ) {
jQuery.event.remove( elem, type );
} else {
removeEvent( elem, type, data.handle );
}
}
}
if ( deleteExpando ) {
delete elem[ jQuery.expando ];
} else if ( elem.removeAttribute ) {
elem.removeAttribute( jQuery.expando );
}
delete cache[ id ];
}
}
}
This looks in the jQuery.cache
object for any event type properties on the events object property of the data object relating to each element that will be deleted when calling .html('')
and removes them.
To basically explain how the standard event binding works, when a function is bound as a handler to an event raised on an element using jQuery, a data object is added as a property to the jQuery.cache
object. This data object contains an events property object that will have a property created on it with a name matching the event type to which you wish to bind the event handler function. this property will contain an array of functions that should be called when the event is raised on the element, so the event handler function is added to this array. If this is the first event handler function for the event type and element in question, the jQuery.event.handle
function with a call to apply (using the element as the context such that this
in the function execution context will refer to the element) is registered with the browser using addEventListener/attachEvent
.
When an event is raised, the jQuery.event.handle
function will call all of the functions in the array on the property of the events property object of the data object matching the event type and the element on which the event was raised.
So in summary, html('')
shouldn't cause memory leaks as a number of defensive measures are in place to prevent them.
Yes, because jQuery maintains a list of the attached event handlers to make unhooking them easier and in order to explicitly unhook them for you when the page is unloaded (which works around a more serious memory leak in IE). (So does Prototype, can't speak for other libs.) The solution is to unhook them before removing the elements (either directly, or via empty
).
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