欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

JavaScript编程开发中jQuery的缓存机制浅析

程序员文章站 2023-11-09 15:56:34
前不久在研究jquery的动画队列的时候,发现jquery的缓存也很强大,尽管以前也稍微接触过,但一直都没有深入研究过。jquery的缓存系统在外部应用的时候都比较简单,比如要将某...

前不久在研究jquery的动画队列的时候,发现jquery的缓存也很强大,尽管以前也稍微接触过,但一直都没有深入研究过。jquery的缓存系统在外部应用的时候都比较简单,比如要将某个url数据存到缓存中只要这么写:

. 代码如下:


var val = "stylechen.com";
$("p").data( "url" ); // 返回undefined
$("p").data( "url", val ); // 返回"stylechen.com"
$("p").data( "url" ); // 返回"stylechen.com"

不光可以存储字符串,上面的val也可以是任意数据,对象、数组、函数等都可以存到里面。仅仅实现这种功能还是挺简单的,声明一个全局对象用来存储数据,然后使用data方法来存储或返回数据:

. 代码如下:


var cachedata = {}; // 用来存储数据的全局对象
var data = function( key, val ){
 if( val !== undefined ){
  cachedata[key] = val;
 }

 return cachedata[key];
}; 

jquery缓存系统的真正魅力在于其内部应用中,动画、事件等都有用到这个缓存系统。之前在写easyanim的时候,我将动画的队列都存储到各dom元素的自定义属性中,这样虽然可以方便的访问队列数据,但也同时带来了隐患。如果给dom元素添加自定义的属性和过多的数据可能会引起内存泄漏,所以要尽量避免这么干。

如果是使用jquery的缓存系统来存放dom元素的数据,会先给该dom元素添加一个随机生成的属性,这个属性用来存放访问缓存数据的索引值,就好比dom元素都有一把开启缓存保险箱的钥匙,只要有了钥匙就可以随时开启缓存保险箱。将本来存放到dom元素中的数据都转到了缓存中,而dom元素本身只要存储一个简单的属性就可以了,这样就可以将由dom元素引起的内存泄漏的风险规避到最小。下面是我模拟jquery自己写的一个简单的缓存系统:

. 代码如下:


var cachedata = {}, // 用来存储数据的全局对象
 uuid = 0,
 // 声明随机数
 expando = "cachedata" ( new date() "" ).slice( -8 );

var data = function( key, val, data ){
 if( typeof key === "string" ){
  if( val !== undefined ){
   cachedata[key] = val;
  }

  return cachedata[key];
 }
 else if( typeof key === "object" ){
  var index,
   thiscache;

  if( !key[expando] ){
   // 添加一个dom元素的属性
   // 随机数是属性名 索引值是属性值
   index = key[expando] = uuid;
   thiscache = cachedata[index] = {};
  }
  else{
   index = key[expando];
   thiscache = cachedata[index];
  }

  
  if( !thiscache[expando] ){
   thiscache[expando] = {};
  }

  if( <a href="https://jb51.net">gambling</a> data !== undefined ){
   // 将数据存到缓存对象中
   thiscache[expando][val] = data;
  }

  // 返回dom元素存储的数据
  return thiscache[expando][val];
 }
};

var removedata = function( key, val ){
 if( typeof key === "string" ){
  delete cachedata[key];
 }
 else if( typeof key === "object" ){
  if( !key[expando] ){
   return;
  }
  // 检测对象是否为空
  var isemptyobject = function( obj ) {
    var name;
    for ( name in obj ) {
     return false;
    }
    return true;
   },

   removeattr = function(){
    try{
     // ie8及标准可以直接使用delete来删除属性
     delete key[expando];
    }
    catch (e) {
     // ie6/ie7使用removeattribute方法来删除属性
     key.removeattribute(expando);
    }
   },

   index = key[expando];

  if( val ){
   // 只删除指定的数据
   delete cachedata[index][expando][val];
   // 如果是空对象 索性全部删除
   if( isemptyobject( cachedata[index][expando] ) ){
    delete cachedata[index];
    removeattr();
   }
  }
  else{
   // 删除dom元素存到缓存中的所有数据
   delete cachedata[index];
   removeattr();
  }
 }
};


上面的代码值得注意的是ie6/ie7中用delete来删除自定义的属性会报错,只能使用removeattribute来删除,标准的浏览器都可以使用delete来删除。下面是调用的结果:

. 代码如下:


var box = document.getelementbyid( "box" ),
 list = document.getelementbyid( "list" );

data( box, "myname", "chen" );
alert( data( box, "myname" ) ); // chen

data( box, "myblog", "stylechen.com" );
alert( data( box, "myblog" ) ); // stylechen.com

removedata( box, "myblog" );

alert( data( box, "myblog" ) ); // undefined
alert( data( box, "myname" ) ); // chen
alert( box[expando] ); // 1

removedata( box );
alert( box[expando] ); // undefined

当然,jquery的缓存系统比我的这个要复杂些,不过核心原理还是一样的。easyanim将会在后续的版本中引入这个缓存系统。