jQuery .html()方法泄漏内存吗?

时间:2021-05-05 09:00:17

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.

我正在构建一个带有requestAnimationFrame循环的游戏,该循环包括对jQuery html()方法的调用。它只是更新游戏操作旁边的状态窗口中的文本。

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:

我注意到Chrome的时间线监视器,DOM节点上升和上升,每分钟数千!当我改变我的代码:

// 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 个解决方案

#1


7  

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:

内存泄漏通常是由Javascript引擎和DOM之间的循环引用引起的。例如:

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.

该脚本获取对页面上div的引用。到目前为止,我们没事。下一行将一个函数分配给DOM上的事件处理程序,创建从DOM到Javascript引擎的引用 - 泄漏的一半。函数体使用标签创建一个Closure--标签引用与函数一起保存,以便将来调用它。这完成了标记 - >函数(DOM - > JS)和函数 - >标记(JS - > DOM)之间的循环引用,因此2将位于内存中,直到浏览器的进程被销毁。

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:

因此,为了使您提到的任何一行代码泄漏,它必须消除具有上述事件附加的标记(或遵循类似模式的数据)。但是,jQuery的.html(字符串)不遗余力地阻止这些:

// 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:

所以它循环遍历标签内的所有标签,你正在运行.html(字符串)并在它们上运行cleanData(),这反过来做到这一点:

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

所以为了使用这种方法泄漏内存而不是浏览器内置的.innerHTML,你必须触发一些非常模糊的浏览器错误(似乎不太可能),或者更可能是其他东西正在发生而你却误以为对于jQuery的.html(字符串)。

#2


2  

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

始终使用.empty()。html(...)而不仅仅是.html()

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

.empty()从您要删除的DOM对象中取消绑定事件侦听器,并正常删除它们。

#1


7  

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:

内存泄漏通常是由Javascript引擎和DOM之间的循环引用引起的。例如:

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.

该脚本获取对页面上div的引用。到目前为止,我们没事。下一行将一个函数分配给DOM上的事件处理程序,创建从DOM到Javascript引擎的引用 - 泄漏的一半。函数体使用标签创建一个Closure--标签引用与函数一起保存,以便将来调用它。这完成了标记 - >函数(DOM - > JS)和函数 - >标记(JS - > DOM)之间的循环引用,因此2将位于内存中,直到浏览器的进程被销毁。

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:

因此,为了使您提到的任何一行代码泄漏,它必须消除具有上述事件附加的标记(或遵循类似模式的数据)。但是,jQuery的.html(字符串)不遗余力地阻止这些:

// 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:

所以它循环遍历标签内的所有标签,你正在运行.html(字符串)并在它们上运行cleanData(),这反过来做到这一点:

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

所以为了使用这种方法泄漏内存而不是浏览器内置的.innerHTML,你必须触发一些非常模糊的浏览器错误(似乎不太可能),或者更可能是其他东西正在发生而你却误以为对于jQuery的.html(字符串)。

#2


2  

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

始终使用.empty()。html(...)而不仅仅是.html()

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

.empty()从您要删除的DOM对象中取消绑定事件侦听器,并正常删除它们。