jQuery泄漏解决了,但为什么呢?

我正在使用大量JavaScript来处理大型企业应用程序。 够了,我无法通过并修复过去5年开发过程中创建的所有小型循环引用。 在研究解决方案时,我遇到了这个小jQuery黑客/补丁:

http://kossovsky.net/index.php/2009/07/ie-memory-leak-jquery-garbage-collector/

并决定尝试一下。 令人惊讶的是,它的作品! sIEVE显示我之前发现的地方没有泄漏,iexplore任务维持更易管理的内存占用。

我的问题是,为什么这有效? jQuery.remove调用.removeChild,它应该摆脱元素,但显然不会。 而是将补丁附加到新的垃圾收集器div上,然后将其清除。 为什么删除补丁方法完全释放了内存,但jQuery的删除function却没有? 我希望能够理解为什么这样做是为了在我检查更大的应用程序之前可能改进解决方案。

这是当前jQuery版本(1.6.2)中的.remove方法。 请注意,它调用.cleanData

 // keepData is for internal use only--do not document remove: function( selector, keepData ) { for ( var i = 0, elem; (elem = this[i]) != null; i++ ) { if ( !selector || jQuery.filter( selector, [ elem ] ).length ) { if ( !keepData && elem.nodeType === 1 ) { jQuery.cleanData( elem.getElementsByTagName("*") ); jQuery.cleanData( [ elem ] ); } if ( elem.parentNode ) { elem.parentNode.removeChild( elem ); } } } return this; }, 

它调用的.cleanData方法,提到了一个票号,并据称可以防止这种可怕的泄漏(根据其中一条评论):

 cleanData: function( elems ) { var data, id, cache = jQuery.cache, internalKey = jQuery.expando, special = jQuery.event.special, deleteExpando = jQuery.support.deleteExpando; for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) { continue; } id = elem[ jQuery.expando ]; if ( id ) { data = cache[ id ] && cache[ id ][ internalKey ]; if ( data && data.events ) { for ( var type in data.events ) { if ( special[ type ] ) { jQuery.event.remove( elem, type ); // This is a shortcut to avoid jQuery.event.remove's overhead } else { jQuery.removeEvent( elem, type, data.handle ); } } // Null the DOM reference to avoid IE6/7/8 leak (#7054) if ( data.handle ) { data.handle.elem = null; } } if ( deleteExpando ) { delete elem[ jQuery.expando ]; } else if ( elem.removeAttribute ) { elem.removeAttribute( jQuery.expando ); } delete cache[ id ]; } } } 

这是评论中提到的票证。 显然它是八个月前修复的:

http://bugs.jquery.com/ticket/7054#comment:10

根据Dave Methvin的说法,解决方案似乎是确保cleanData删除事件处理程序中的DOM元素ref以避免IE6 / 7/8内存泄漏。

换句话说,在事件处理程序中将对DOM元素的引用设置为null否则一些非常棒的浏览器,而不提及任何名称咳嗽 IE 咳嗽将泄漏内存。

discardElement (来自您的链接)将元素插入到容器中,然后清空容器,从而使对该元素的任何引用无效

考虑到这一点,我建议升级jQuery。 你指的文章来自2009年,两年大约相当于jQuery开发时间的四百万个工时。

最后,这里有一些关于Internet Explorer中泄漏模式的有趣(并且可笑很长)的阅读:

  • 了解和解决Internet Explorer泄漏模式

我要理解它与.net垃圾收集类似,因为它依赖于堆中的固定对象。

IE正在处理已删除对象的父级,如引脚,而不是正确清除已删除的对象。

将已删除的项目移动到此生成的gc容器的行为基本上是删除该引脚,因为IE知道没有任何东西依赖于该容器。

无论如何,那是我的直觉。