在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 。 比较Esailija的评论为什么.remove()
方法,你的mem将被立即清除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的问题,以及我发现的一些事情。