我的JavaScript代码创建了一个LI
元素列表。当我更新列表时,内存用量会增加并且从未下降。我在sIEve中进行了测试,并显示浏览器保留了所有应该通过$.remove()
或$.empty
jQuery命令删除的元素。
如何才能在不造成内存泄漏的情况下删除DOM节点?
请参阅我的其他问题以查看具体代码。
我的JavaScript代码创建了一个LI
元素列表。当我更新列表时,内存用量会增加并且从未下降。我在sIEve中进行了测试,并显示浏览器保留了所有应该通过$.remove()
或$.empty
jQuery命令删除的元素。
如何才能在不造成内存泄漏的情况下删除DOM节点?
请参阅我的其他问题以查看具体代码。
DOM会保留所有DOM节点,即使它们已经从DOM树中被移除,唯一的删除这些节点的方法就是进行页面刷新(如果将列表放入iframe中,则刷新不会那么明显)。
否则,你可以等待问题变得严重到浏览器的垃圾回收程序被迫采取行动(这里需要数百兆字节的未使用节点)。
最佳实践是重用节点。
编辑:尝试这个:
var garbageBin;
window.onload = function ()
{
if (typeof(garbageBin) === 'undefined')
{
//Here we are creating a 'garbage bin' object to temporarily
//store elements that are to be discarded
garbageBin = document.createElement('div');
garbageBin.style.display = 'none'; //Make sure it is not displayed
document.body.appendChild(garbageBin);
}
function discardElement(element)
{
//The way this works is due to the phenomenon whereby child nodes
//of an object with it's innerHTML emptied are removed from memory
//Move the element to the garbage bin element
garbageBin.appendChild(element);
//Empty the garbage bin
garbageBin.innerHTML = "";
}
}
要在您的上下文中使用它,您需要按照以下方式进行:
discardElement(this);
这更像是一条提示而非实际答案,但它也相当有趣。
来自W3C DOM核心规范(http://www.w3.org/TR/DOM-Level-2-Core/core.html):
核心DOM API旨在与各种语言兼容,包括普通用户脚本语言和大多由专业程序员使用的更具挑战性的语言。因此,DOM API需要在各种内存管理哲学之间运行,从根本上不公开内存管理的语言绑定,通过(特别是Java)提供显式构造函数但提供自动垃圾收集机制以自动回收未使用的内存,到那些(尤其是C / C ++)通常要求程序员明确分配对象内存,追踪其使用情况并显式释放以供重用。为了确保这些平台上的一致API,DOM根本不涉及内存管理问题,而是将这些留给实现。 DOM API定义的任何显式语言绑定(用于ECMAScript和Java)都不需要任何内存管理方法,但其他语言(尤其是C或C ++)的DOM绑定可能需要此类支持。这些扩展将由适应DOM API到特定语言的人负责,而不是DOM工作组。
换句话说:内存管理由不同语言中DOM规范的实现来处理。要找出从javascript中删除DOM对象的任何方法(而不是hack),您必须查阅DOM实现的文档。(但是,MDC网站上关于该主题的信息非常少。)
关于jQuery#remove
和jQuery#empty
的说明:据我所知,这两种方法都没有除了从DOM node
中删除 Object
或从文档
中删除DOM node
之外的其他操作。它们只是移除。当然,这并不意味着这些对象没有分配内存(即使它们不在 document
中)。
编辑:上面的内容多余了,因为显然jQuery不能奇迹般地解决并绕过所用浏览器的DOM实现。
jQuery
的段落。 - FK82你是否移除了任何事件监听器?那可能会导致内存泄漏。
<html>
<head></head>
<body>
<a href="javascript:" onclick="addRemove(this)">add</a>
<ul></ul>
<script>
function addRemove(a) {
var ul = document.getElementsByTagName('UL')[0],
li, i = 20000;
if (a.innerHTML === 'add') {
while (i--) {
li = document.createElement('LI');
ul.appendChild(li);
li.innerHTML = i;
li.onclick = function() {
alert(this.innerHTML);
};
}
a.innerHTML = 'remove';
} else {
while (ul.firstChild) {
ul.removeChild(ul.firstChild);
}
a.innerHTML = 'add';
}
}
</script>
</body>
</html>
也许你可以尝试与你的代码进行比较,我知道当你先将节点插入DOM中,然后再对其进行操作时(例如:附加事件或填充其 innerHTML
属性),IE泄漏要少得多。
https://crockford.com/javascript/memory/leak.html
或者使用这个闭包修复的解决方法: