我正在使用 chrome 开发工具来确定某些 JS 代码中是否存在内存泄漏。内存时间线看起来不错,内存按预期回收。
但是,内存快照令人困惑,因为“分离的 DOM 树”下存在条目,因此看起来好像存在泄漏。
“分离的 DOM 树”下的东西是等待垃圾收集还是这些真正的泄漏?
还有人知道如何找出对分离元素的引用是什么函数吗?
我正在使用 chrome 开发工具来确定某些 JS 代码中是否存在内存泄漏。内存时间线看起来不错,内存按预期回收。
但是,内存快照令人困惑,因为“分离的 DOM 树”下存在条目,因此看起来好像存在泄漏。
“分离的 DOM 树”下的东西是等待垃圾收集还是这些真正的泄漏?
还有人知道如何找出对分离元素的引用是什么函数吗?
这些元素在您的代码中被引用,但它们与页面的主 DOM 树断开连接。
简单的例子:
var a = document.createElement("div");
a
a
现在引用一个断开连接的元素,当它仍在范围内时,它不能被 GC'd 。
如果分离的 dom 树在内存中持续存在,那么您将保留对它们的引用。使用 jQuery 做到这一点有点容易,只需保存对遍历结果的引用并保留它。例如:
var parents = $("span").parent("div");
$("span").remove();
现在跨度被引用,即使看起来你无论如何都没有引用它们。通过 jQuery属性parents
间接保持对所有跨度的引用。.prevObject
这样做parents.prevObject
会给出引用所有跨度的对象。
请参阅此处的示例http://jsfiddle.net/C5xCR/6/。尽管没有直接显示跨度会被引用,但它们实际上是由parents
全局变量引用的,您可以看到 Detached DOM 树中的 1000 个跨度永远不会消失。
现在这是相同的 jsfiddle,但具有:
delete parents.prevObject
你可以看到跨度不再在分离的 dom 树中,或者任何地方。http://jsfiddle.net/C5xCR/7/
“分离的 DOM 树”下的东西是等待垃圾收集还是这些真正的泄漏?
在拍摄快照之前,浏览器将运行垃圾收集并清除所有未引用的对象。所以堆快照总是只包含活动对象。因此,如果快照中存在分离的 DOM 树,则树中必须有一个从 JavaScript 引用的元素。
还有人知道如何找出对分离元素的引用是什么函数吗?
在同一个分离的 DOM 树中应该有一个元素(或其中几个)具有黄色背景。这些元素是从 JavaScript 代码中引用的。您可以找出谁确切地保留了对保留树中元素的引用。
既然你已经添加了 jQuery 标签,我就偷偷地怀疑这是一个 jQuery的东西。一个快速的谷歌把我带到了这个页面。使用 jQ 的detach
方法时,对对象的引用仍保存在内存中,因此可能会导致您的快照。
另一件事可能是 jQuerydiv
手头有一个节点,该节点 - 显然 - 保存在内存中,但从未添加到实际的 dom 中......有点document.createNode('div')
不附加它。这也将显示在内存快照中。你无法解决这个问题,jQuery 使用它将字符串解析为 html 元素。
因此,要从内存中删除一些元素,请使用 jQuery。cf Esailija 关于为什么.remove()
方法,您的内存将立即被清除remove
不完全符合这里的要求的评论。
$('#someElem')[0].parentNode.removeChild($('#someElem')[0]);
应该完全删除元素,但可能不会取消绑定事件。也许是这样的:
$('#someElem').detach();//to remove any event listeners
$('#someElem')[0].parentNode.removeChild($('#someElem')[0]);//remove element all together
而且,正如 Esailija 在他的回答中指出的那样,确保将对任何 jQuery 对象 ( var someRef= $('.someSelector');
) 的引用分配给全局变量,因为它们不会被 GC 处理。事实上,只要避免全局变量。
但是要简短而清楚地回答您的问题:不,这些不是真正的内存泄漏,应该在onbeforeunload
事件中释放内存。jQuery 对象被删除,因此所有引用都超出了范围。至少,这就是我的“研究”让我相信的。也许不完全相关,但只是作为参考这是我不久前发布的关于 mem-leaks 的问题,并通过它发现了一些事情..