首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >javascript内存泄漏

javascript内存泄漏
EN

Stack Overflow用户
提问于 2010-02-23 16:36:57
回答 5查看 8.9K关注 0票数 18

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

DOM

代码语言:javascript
复制
<div id="parent"></div>

JS

代码语言:javascript
复制
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();

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

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

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2010-02-24 05:50:07

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

来自1.4.2源代码

代码语言:javascript
复制
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;
}

我们可以看到调用了jQuery.cleanData()函数。这是它的源码

代码语言:javascript
复制
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 ];
        }
    }
}

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

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

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

所以总而言之,html('')不应该导致内存泄漏,因为有许多防御措施可以防止它们。

票数 19
EN

Stack Overflow用户

发布于 2010-02-23 16:42:36

无法对泄漏问题发表评论,但您可以简单地使用.empty()而不是.html('')。这样,您就可以清理innerHTML并删除任何绑定的事件处理程序。

票数 2
EN

Stack Overflow用户

发布于 2010-02-23 16:45:02

是的,因为jQuery维护了一个附加的事件处理程序列表,以便更容易地解除它们的挂钩,并在页面卸载时显式地为您解除挂钩(这解决了IE中更严重的内存泄漏问题)。( Prototype也是如此,不能为其他库说话。)解决方案是在删除元素之前解除它们的连接(直接或通过empty)。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2316726

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档