jquery源码分析之jQuery缓存处理

jquery框架在实现过程中对性能优化也做了很多处理,其中使用缓存就是重要的性能优化手段。

实现原理是从对象属性中取值,如果取值为undefined,则为此对象属性赋值,如果取值不为undefined,则直接返回,这样当在页面多次取对象属性值时,可以直接返回之前设置值,避免重复赋值,从而提高页面性能。如下代码模拟jQeruy实现了缓存方法

function TestCache() {
		}
		
		TestCache.prototype = {
			cache: function(owner) {
				var value = owner["cache"];
				
				if (!value) {
					value = {};
					owner["cache"] = value;
				}
				return value;
			}
		};

使用缓存

var testCache = new TestCache();
var owner = {};
// 第一次从缓存取值,缓存不存在,则初始化
var noCache = testCache.cache(owner);
// 给缓存返回值进行赋值
noCache["name"] = "zhangsan";
noCache["age"] = 28;
noCache["handle"] = function() {
   alert(this.name + "---" + this.age);
};		}
// 第二次从缓存取值,直接获取
var useCache = testCache.cache(owner);
useCache.handle();

jQuery缓存实现

function Data() {
	this.expando = jQuery.expando + Data.uid++;
}
Data.uid = 1;
Data.prototype = {
...
    // 提供缓存方法
    cache: function( owner ) {
		// We can accept data for non-element nodes in modern browsers,
		// but we should not, see #8335.
		// Always return an empty object.
		if ( !acceptData( owner ) ) {
			return {};
		}
		// Check if the owner object already has a cache
        // 从对象属性中取缓存值
		var value = owner[ this.expando ];
		// If not, create one
        // 如果不存在,则创建
		if ( !value ) {
			value = {};
			// We can accept data for non-element nodes in modern browsers,
			// but we should not, see #8335.
			// Always return an empty object.
			if ( acceptData( owner ) ) {
				// If it is a node unlikely to be stringify-ed or looped over
				// use plain assignment
				if ( owner.nodeType ) {
                    // 向对象属性赋值,即缓存了value对象
					owner[ this.expando ] = value;
				// Otherwise secure it in a non-enumerable property
				// configurable must be true to allow the property to be
				// deleted when data is removed
				} else {
					Object.defineProperty( owner, this.expando, {
						value: value,
						configurable: true
					} );
				}
			}
		}
        // 返回缓存值
		return value;
	},
    // 通过get方法取得缓存对象
    get: function( owner, key ) {
		return key === undefined ?
			this.cache( owner ) :
			owner[ this.expando ] && owner[ this.expando ][ key ];
	},
...
} 
// 实例化Data对象
var dataPriv = new Data();

在jQuery.event.add方法中初始化缓存对象

jQuery.event = {
   ...
   add: function( elem, types, handler, data, selector ) {
      // 从缓存中获取对象,如果缓存中不存在,则初始化缓存对象
      var elemData = dataPriv.get( elem );
      // 以下对缓存对象进行属性增强
      if ( !( events = elemData.events ) ) {
	     events = elemData.events = {};
      }
      if ( !( eventHandle = elemData.handle ) ) {
	     eventHandle = elemData.handle = function( e ) {
	     ...
	     }
      }
   ...
      while ( t-- ) {
      ...
         // handleObj is passed to all event handlers
	     handleObj = jQuery.extend( {
		    type: type,
		    origType: origType,
		    data: data,
		    handler: handler,
		    guid: handler.guid,
		    selector: selector,
		    needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
		    namespace: namespaces.join( "." )
          }, handleObjIn );
	      if ( !( handlers = events[ type ] ) ) {
	         handlers = events[ type ] = [];
		     handlers.delegateCount = 0;
	      }
	      handlers.push( handleObj );
      ...
      }
   }
...
}

在jQuery.event.dispatch方法中使用缓存

jQuery.event = {
   ...
   dispatch: function( event ) {
      // 取出缓存值,"events"属性是通过jQuery.event.add方法中对缓存对象进行了属性增强而得到
      var handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [],
      ...
   }
   ...
}

相关推荐