jQuery leaks solved, but why?

后端 未结 2 1771
栀梦
栀梦 2021-02-19 17:01

I am working on a large enterprise application with a LOT of JavaScript. Enough that I can\'t possibly go through and fix all the small circular references that have been create

2条回答
  •  你的背包
    2021-02-19 17:54

    This is the .remove method in the current jQuery release (1.6.2). Notice that it calls .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;
        },
    

    And the .cleanData method which it calls, which mentions a ticket number and allegedly prevents that horrible leak (according to one of the comments):

    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 ];
                }
            }
        }
    

    And here is the ticket mentioned in the comment. Apparently it was fixed eight months ago:

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

    According to Dave Methvin the solution seems to be to Ensure that the DOM element ref in an event handler is removed by cleanData to avoid an IE6/7/8 memory leak.

    In other words, set references to DOM elements within event handlers to null otherwise some awesome browsers, without mentioning any names cough IE cough will leak memory.

    discardElement (from your link) inserts the element into a container, and then empties the container, thereby nullifying any references to that element.

    With that in mind, I would suggest upgrading jQuery. The article you point to is from 2009, and two years is roughly equivalent to four-hundred-zillion man hours of jQuery development time.

    Finally, here is some interesting (and ridiculously long) reading on leak patterns in Internet Explorer:

    • Understanding and Solving Internet Explorer Leak Patterns

提交回复
热议问题