use*_*903 15 jquery dom memory-leaks
我看到注册的事件处理程序.on()是在$.cache.我也看到事件处理程序也被保留了$(elem).data().
保留的对象是$.cache指注册事件的DOM节点.当DOM节点分离时,这会导致内存泄漏,这会使.off()调用成为必需的.
我有一种情况,我不知道DOM节点(我附加事件处理程序)何时被分离.虽然我可以在我的代码中保存对该DOM节点的引用并调用.off()清理,但它看起来并不好,因为知道何时删除DOM节点并不是直截了当的.
做这个的最好方式是什么?
小智 16
"做这个的最好方式是什么?"
如果您要使用jQuery,则必须使用其API来删除元素,并且必须使用正确的方法,否则,如您所述,您将有内存泄漏.
如果您不知道DOM节点何时被删除,以及是否导致泄漏,我认为这意味着您正在使用另一个库和jQuery.出于这个原因,这不是一个好主意.
您需要确保jQuery删除受jQuery影响的任何元素.还有一些$.cache您未明确设置的数据存储.这意味着应该使用jQuery删除所有元素,而不仅仅是那些您认为可能包含数据的元素.
"
$.cachejQuery 的目的是什么?"
将处理程序和其他数据与元素相关联.数据和元素之间的链接基本上是存储在元素上的expando属性上的序列号.
如果在没有jQuery的情况下删除元素,则关联的数据$.cache将成为孤立的.
这种方法的目的是防止潜在的泄漏.不幸的是,它可能会造成更严重的泄漏.
我遇到了类似的情况,其中Knockout用于添加和删除文档中的dom树.但是,jquery用于将事件侦听器附加到这些dom树.当knockout从文档中删除dom元素时,侦听器不会被解除绑定,因此dom树永远不会有资格进行垃圾回收.我们添加了一个清理函数,每次哈希更改时都会遍历jquery $ .cache,并找到绑定到文档中不存在的dom树的处理程序.然后它取消绑定听众,从而使得dom树有资格进行垃圾收集并修复我们看到的大部分泄漏,即用于泄漏13MB的应用程序的往返行程,现在它在这些变化到位时仅泄漏3MB.
for (var i in $.cache) {
if ($.cache.hasOwnProperty(i)) {
if ($.cache[i].handle && $.cache[i].handle.elem && document !== $.cache[i].handle.elem && !jQuery.contains(document, $.cache[i].handle.elem)) {
//we have an event handler pointing to a detached dom element!
//this is a memory leak as this detached dom element cannot be garbage collected until
//all references to it are removed. So lets delete the event handler to get memory back!
var orphan = $($.cache[i].handle.elem);
$('body').append(orphan);
orphan.off();
orphan.remove();
orphan = null;
}
}
}
Run Code Online (Sandbox Code Playgroud)