javascript内存泄漏

Pra*_*sad 18 javascript jquery

我正在使用jquery并做这样的事情

DOM:

<div id="parent"></div>
Run Code Online (Sandbox Code Playgroud)

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

现在我的问题是,做绑定事件,DOM然后只是从DOM导致内存泄漏中删除元素?

如果是,如何解决这个问题?

Rus*_*Cam 19

jQuery html方法尝试通过删除因调用.html('')jQuery对象而删除的任何元素的事件处理程序来防止内存泄漏.

从1.4.2源码

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

我们可以看到该jQuery.cleanData()函数被调用.这是其中的来源

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

这将在jQuery.cache对象中查找与调用时将删除的每个元素相关的数据对象的事件对象属性上的任何事件类型属性,并将其删除.html('').

为了基本解释标准事件绑定的工作原理,当函数绑定为使用jQuery在元素上引发的事件的处理程序时,数据对象将作为属性添加到jQuery.cache对象.此数据对象包含一个events属性对象,该对象将在其上创建一个属性,其名称与您希望绑定事件处理函数的事件类型相匹配.此属性将包含在元素上引发事件时应调用的函数数组,因此事件处理函数将添加到此数组中.如果这是有问题的事件类型和元素的第一个事件处理函数,则jQuery.event.handle使用调用apply(使用元素作为上下文,使得this在函数执行上下文中将引用元素)的函数使用浏览器注册addEventListener/attachEvent.

引发事件时,该jQuery.event.handle函数将在与事件类型匹配的数据对象的events属性对象的属性以及引发事件的元素上调用数组中的所有函数.

因此总的来说,html('')不应该导致内存泄漏,因为一些防御措施已到位以防止它们.