在chrome开发工具中查找JS内存泄漏

我正在使用chrome dev工具来判断在某些JS代码中是否有内存泄漏。 内存时间线看起来不错,内存正如预期的那样被回收。

在这里输入图像说明

但是, 内存快照很容易混淆,因为看起来好像有泄漏,因为在“分离的DOM树”下有条目。

“Detached DOM Tree”下的东西是否等待被垃圾收集或是真正的泄漏?

也没有人知道如何找出什么function是坚持一个分离的元素的引用?

在这里输入图像说明

这些元素在您的代码中被引用,但是它们从页面的主DOM树中断开。

简单的例子:

var a = document.createElement("div"); 

现在引用一个断开的元素,当a仍然在范围内时,它不能被GC'd。

如果分离的dom树坚持在记忆中,那么你保持对它们的引用。 使用jQuery来做这件事很简单,只需保存一个遍历结果的引用并保持这个引用。 例如:

 var parents = $("span").parent("div"); $("span").remove(); 

现在跨度被引用,即使它没有出现你不pipe怎样引用它们。 parents通过.prevObject属性间接保持对所有跨度的引用。 所以做parents.prevObject会给那个引用所有跨度的对象。

看到这里的例子http://jsfiddle.net/C5xCR/6/ 。 即使不直接显示跨度将被引用,但实际上它们是由parents全局variables引用的,您可以看到分离的DOM树中的1000个跨度永远不会消失。

现在这里是相同的jsfiddle,但是:

 delete parents.prevObject 

你可以看到这些跨度已经不再是孤立的dom树,或者任何地方。 http://jsfiddle.net/C5xCR/7/

“Detached DOM Tree”下的东西是否等待被垃圾收集或是真正的泄漏?

在拍摄快照之前,浏览器将运行垃圾收集并扫描所有未被引用的对象。 所以堆快照总是只包含活动对象。 因此,如果分离的DOM树位于快照中,则必须在JavaScript中引用树中的元素。

也没有人知道如何找出什么function是坚持一个分离的元素的引用?

在同一个分离的DOM树中应该有一个元素(或其中的几个),它们具有黄色背景。 这些元素是从JavaScript代码引用的。 您可以找出究竟是谁在引用树中的元素。

既然你已经添加了jQuery标签,我对这个jQuery的东西有一个偷偷摸摸的怀疑。 快速谷歌带我到这个页面 。 当使用jQ的detach方法时,对象的引用仍然保留在内存中,因此可能会导致快照。

另一件事情可能是,jQuery手头有一个div节点,显然它保存在内存中,但是从来没有添加到实际的dom中。一种document.createNode('div')没有添加它。 这也将显示在内存快照中。 你不能绕过这个,jQuery使用它来parsingstring到html元素。

所以要从内存中删除一些元素, 使用jQuery .remove()方法,你的mem将被立即清除比较Esailija的评论为什么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'); )的引用赋值给全局variables,因为它们不会被GC化。 事实上,只是全盘避免全局。
但是要简要地回答你的问题,并且清楚地表明:没有这些不是真正的内存泄漏,内存应该在onbeforeunload事件上被释放。 jQuery对象被删除,所以所有的引用超出了范围。 至less,这就是我的“研究”让我相信的东西。 也许不完全相关,但仅仅作为一个参考这里是一个关于我后来发布的mem-leaks的问题,以及我发现的一些事情。