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

JPR*_*PRO 13 javascript jquery dom

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

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

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

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

kar*_*m79 12

这是.remove当前jQuery版本(1.6.2)中的方法.请注意它调用.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;
    },
Run Code Online (Sandbox Code Playgroud)

.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 ];
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

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

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中泄漏模式的有趣(并且可笑很长)的阅读: