javascript内存泄漏

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

DOM

 

JS

 var _doSomeThing = function() { //some codes } $(function() { // appending div and binding methods to span $('#parent').append('1'); $('#parent').append('2'); $('#parent span').bind('click', _doSomeThing); }); function _clearDiv() { //clear div $('#parent').html(''); } //sometime in future, call clear div _clearDiv(); 

现在我的问题是,对DOM进行绑定事件,之后只是从DOM删除元素会导致内存泄漏吗?

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

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

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

我们可以看到调用了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 ]; } } } 

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

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

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

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

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

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

你总是可以使用$('#parent span').unbind(); 只是要确定

由于您经常引用$(’#parent’),因此您应该在全局范围内创建对该对象的引用,以便jQuery不会在每个请求上不断查找该对象。 这样做,你基本上缓存了对象的引用,这将极大地减少内存使用量。

 _parent = $('#parent'); 

 function(){ _parent.append('1'); } 

编辑:我从这篇关于jQuery性能规则的文章中选择了这个技巧