我正在使用jquery并做类似这样的事情
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();
现在我的问题是,将事件绑定到DOM
,然后再从DOM
中删除元素是否会导致内存泄漏?
如果是,如何解决这个问题?
发布于 2010-02-24 05:50:07
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
对象添加一个数据对象作为属性。此数据对象包含一个事件属性对象,该对象将在其上创建一个属性,其名称与您希望将事件处理函数绑定到的事件类型相匹配。此属性将包含一个函数数组,当在元素上引发事件时应调用这些函数,因此将事件处理函数添加到此数组中。如果这是有问题的事件类型和元素的第一个事件处理函数,则使用addEventListener/attachEvent
向浏览器注册要应用的jQuery.event.handle
函数(使用元素作为上下文,以便函数执行上下文中的this
将引用该元素)。
当引发事件时,jQuery.event.handle
函数将在与事件类型和引发事件的元素匹配的数据对象的events属性对象的属性上调用数组中的所有函数。
所以总而言之,html('')
不应该导致内存泄漏,因为有许多防御措施可以防止它们。
发布于 2010-02-23 16:42:36
无法对泄漏问题发表评论,但您可以简单地使用.empty()
而不是.html('')
。这样,您就可以清理innerHTML并删除任何绑定的事件处理程序。
发布于 2010-02-23 16:45:02
是的,因为jQuery维护了一个附加的事件处理程序列表,以便更容易地解除它们的挂钩,并在页面卸载时显式地为您解除挂钩(这解决了IE中更严重的内存泄漏问题)。( Prototype也是如此,不能为其他库说话。)解决方案是在删除元素之前解除它们的连接(直接或通过empty
)。
https://stackoverflow.com/questions/2316726
复制相似问题