Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

does jQuery .html() method leak memory?

I am building a game with a requestAnimationFrame loop that includes a call to jQuery html() method. It just updates the text in a status window next to the game action.

I notice with Chrome's timeline monitor, that the DOM nodes go up and up and up, thousands in a minute! And when I change my code from:

// creates a ton of DOM nodes
$("#readout").html(data);

to

// DOM nodes does not increase over time
document.getElementById('readout').innerHTML = data;

the 'memory leak' goes away.

like image 257
pinhead Avatar asked Nov 27 '12 20:11

pinhead


People also ask

What does jQuery html () do?

jQuery html() Method The html() method sets or returns the content (innerHTML) of the selected elements. When this method is used to return content, it returns the content of the FIRST matched element. When this method is used to set content, it overwrites the content of ALL matched elements.

What is the difference between text () and HTML () methods in jQuery for get and set HTML elements?

html() is used to return or change the html and text content of an element. text() can only return or change the text content of an element.


2 Answers

Short answer: No.

Long answer: You likely have something else going on in your page/code.

A memory leak is generally caused by a circular reference between the Javascript engine and the DOM. For example:

var div = document.getElementById('divId');
div.onclick = function() {
    doSomething(div);
};

The script obtains a reference to a div on the page. So far we're fine. The next line assigns a function to an event handler on the DOM, creating a reference from the DOM to the Javascript engine - half way to a leak. The function body uses the tag, which creates a Closure - the tag reference is kept with the function for future calls to it. That completes the circular reference between the tag -> function (DOM -> JS) and function -> tag (JS -> DOM), and so the 2 will sit in memory until the browser's process is destroyed.

So in order for either line of code you mentioned to leak, it would have to be eliminating tags that had events attached like above (or data that follows a similar pattern). But, jQuery's .html(string) goes out of its way to prevent these:

// Remove element nodes and prevent memory leaks
elem = this[i] || {};
if ( elem.nodeType === 1 ) {
    jQuery.cleanData( getAll( elem, false ) );
    elem.innerHTML = value;
}

So it's looping through all the tags inside the tag you're running .html(string) on and running cleanData() on them, which in turn does this:

jQuery.removeEvent( elem, type, data.handle );

Thus preventing the leak.

So in order to leak memory with this method and not the browser built-in .innerHTML you'd have to be triggering some very obscure browser bug (seems pretty unlikely), or more likely something else is going on and you're mistaking it for jQuery's .html(string).

like image 102
Chris Moschini Avatar answered Oct 21 '22 03:10

Chris Moschini


Always use .empty().html(...) instead of just .html()

.empty() unbinds the event listeners from the DOM objects you are about to remove, and removes them gracefully.

like image 42
Serban Avatar answered Oct 21 '22 03:10

Serban