Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
441 views
in Technique[技术] by (71.8m points)

jquery - javascript memory leaks

i am using jquery and doing something like this

DOM:

<div id="parent"></div>

JS:

var _doSomeThing = function()
{
    //some codes
}

$(function()
{
    // appending div and binding methods to span
    $('#parent').append('<span>1</span>');
    $('#parent').append('<span>2</span>');
    $('#parent span').bind('click', _doSomeThing);
});

function _clearDiv()
{
    //clear div
    $('#parent').html('');
}

//sometime in future, call clear div
_clearDiv();

Now my question is, do binding events to DOM and later just removing the elements from DOM leads to memory leakage?

If yes, how to solve this problem?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

the jQuery html method attempts to prevent memory leaks by removing event handlers for any elements that are deleted as a result of calling .html('') on a jQuery object.

From the 1.4.2 source

html: function( value ) {
    if ( value === undefined ) {
        return this[0] && this[0].nodeType === 1 ?
        this[0].innerHTML.replace(rinlinejQuery, "") :
            null;
    } 
    // See if we can take a shortcut and just use innerHTML
    // THE RELEVANT PART
    else if ( typeof value === "string" && !rnocache.test( value ) &&
        (jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&
        !wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) {

        value = value.replace(rxhtmlTag, fcloseTag);

        try {
            for ( var i = 0, l = this.length; i < l; i++ ) {
                // Remove element nodes and prevent memory leaks
               if ( this[i].nodeType === 1 ) {
                   jQuery.cleanData( this[i].getElementsByTagName("*") );
                   this[i].innerHTML = value;
                }
            }

        // If using innerHTML throws an exception, use the fallback method
        } 
        catch(e) {
            this.empty().append( value );
        }
    } 
    else if ( jQuery.isFunction( value ) ) {
        this.each(function(i){
            var self = jQuery(this), old = self.html();
            self.empty().append(function(){
                return value.call( this, i, old );
            });
        });

    }
    else {
        this.empty().append( value );
    }
    return this;
}

We can see that the jQuery.cleanData() function is called. Here is the source for that

cleanData: function( elems ) {
    var data, id, cache = jQuery.cache,
        special = jQuery.event.special,
        deleteExpando = jQuery.support.deleteExpando;

    for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
        id = elem[ jQuery.expando ];

        if ( id ) {
            data = cache[ id ];

            if ( data.events ) {
                for ( var type in data.events ) {
                    if ( special[ type ] ) {
                        jQuery.event.remove( elem, type );

                    } else {
                        removeEvent( elem, type, data.handle );
                    }
                }
            }

            if ( deleteExpando ) {
                delete elem[ jQuery.expando ];

            } else if ( elem.removeAttribute ) {
                elem.removeAttribute( jQuery.expando );
            }

            delete cache[ id ];
        }
    }
}

This looks in the jQuery.cache object for any event type properties on the events object property of the data object relating to each element that will be deleted when calling .html('') and removes them.

To basically explain how the standard event binding works, when a function is bound as a handler to an event raised on an element using jQuery, a data object is added as a property to the jQuery.cache object. This data object contains an events property object that will have a property created on it with a name matching the event type to which you wish to bind the event handler function. this property will contain an array of functions that should be called when the event is raised on the element, so the event handler function is added to this array. If this is the first event handler function for the event type and element in question, the jQuery.event.handle function with a call to apply (using the element as the context such that this in the function execution context will refer to the element) is registered with the browser using addEventListener/attachEvent.

When an event is raised, the jQuery.event.handle function will call all of the functions in the array on the property of the events property object of the data object matching the event type and the element on which the event was raised.

So in summary, html('') shouldn't cause memory leaks as a number of defensive measures are in place to prevent them.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...