五、数据缓存Data4——jQuery.cleanData(elems)
// 代码行:5843——5875 // 方法jQuery.cleanData(elems)用于移除多个DOM元素关联得全部数据和事件,尽在jQuery内部使用。当通过jquery方法移除DOM元素时,jQuery必须确保关联的数据和事件也被移除,以避免内存泄漏。 cleanData: function( elems ) { // 参数elems是待移除数据和事件得DOM元素数组 var data, elem, type, // jQuery.event.special是特殊事件修正对象得集合 special = jQuery.event.special, i = 0; // 把elems[i]赋值给elem,并检测是否为undefined for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { if ( acceptData( elem ) ) { if ( ( data = elem[ dataPriv.expando ] ) ) { // 如果DOM元素关联得数据缓存对象含有属性events,说明在该元素上(他Jon该国jQuery事件方法)绑定过事件,则移除该元素上绑定得所有类型得事件 if ( data.events ) { // 属性data.events是该DOM元素得事件缓存对象,存储了该DOM元素得所有事件;属性data.handle是该DOM元素得主监听函数,是该DOM元素上所有事件响应得统一入口。 // 如果某个事件需要特殊得移除行为,则需要调用方法jQuery.event.remove( elem, type )移除属性events中得所有事件监听函数和主事件监听函数data.handle,并删除数据缓存对象data.events;否则可以执行jQuery.removeEvent()直接移除主事件监听函数data.handle, for ( type in data.events ) { if ( special[ type ] ) { jQuery.event.remove( elem, type ); // This is a shortcut to avoid jQuery.event.remove's overhead } else { jQuery.removeEvent( elem, type, data.handle ); } } } // Support: Chrome <=35 - 45+ // Assign undefined instead of using delete, see Data#remove elem[ dataPriv.expando ] = undefined; } // 移除DOM元素上扩展得jQuery.expando属性 if ( elem[ dataUser.expando ] ) { // Support: Chrome <=35 - 45+ // Assign undefined instead of using delete, see Data#remove elem[ dataUser.expando ] = undefined; } } } } // 代码行:5933——5944 // 方法.empty()在移除匹配元素得所有子元素之前,会先调用方法jQuery.cleanData()移除所有子元素关联得数据和事件。 empty: function() { var elem, i = 0; for ( ; ( elem = this[ i ] ) != null; i++ ) { if ( elem.nodeType === 1 ) { // Prevent memory leaks jQuery.cleanData( getAll( elem, false ) ); // Remove any remaining nodes elem.textContent = ""; } } return this; }, // 代码行:5960——5997 // .html(value)返回或设置HTML内容,通过调用access()方法实现。在设置属性innerHTML之前,会先调用方法jQuery.cleanData(elems)移除所有子元素关联的数据和事件。 html: function( value ) { return access( this, function( value ) { var elem = this[ 0 ] || {}, i = 0, l = this.length; if ( value === undefined && elem.nodeType === 1 ) { return elem.innerHTML; } // See if we can take a shortcut and just use innerHTML if ( typeof value === "string" && !rnoInnerhtml.test( value ) && !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { value = jQuery.htmlPrefilter( value ); try { for ( ; i < l; i++ ) { elem = this[ i ] || {}; // Remove element nodes and prevent memory leaks if ( elem.nodeType === 1 ) { jQuery.cleanData( getAll( elem, false ) ); elem.innerHTML = value; } } elem = 0; // If using innerHTML throws an exception, use the fallback method } catch ( e ) {} } if ( elem ) { this.empty().append( value ); } }, null, value, arguments.length ); },