does jQuery .html() method leak memory?

2019-03-18 10:51发布

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.

2条回答
霸刀☆藐视天下
2楼-- · 2019-03-18 11:35

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).

查看更多
太酷不给撩
3楼-- · 2019-03-18 11:39

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.

查看更多
登录 后发表回答