jQuery的缓存机制浅析


Posted in Javascript onJune 07, 2014

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

var val = "stylechen.com";
$("div").data( "url" ); // 返回undefined
$("div").data( "url", val ); // 返回"stylechen.com"
$("div").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="http://3water.com">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将会在后续的版本中引入这个缓存系统。

Javascript 相关文章推荐
来自qq的javascript面试题
Jul 24 Javascript
当鼠标移动到图片上时跟随鼠标显示放大的图片效果
Jun 06 Javascript
Jquery $when done then的用法详解
May 20 Javascript
ECMAScript6轮播图实践知识总结
Aug 17 Javascript
Javascript typeof与instanceof的区别
Oct 18 Javascript
原生js实现addclass,removeclass,toggleclasss实例
Nov 24 Javascript
angularjs实现过滤并替换关键字小功能
Sep 19 Javascript
Node.js使用Koa搭建 基础项目
Jan 08 Javascript
浅谈webpack 自动刷新与解析
Apr 09 Javascript
微信小程序图表插件wx-charts用法实例详解
May 20 Javascript
ElementUI中el-tree节点的操作的实现
Feb 27 Javascript
vue实现下拉菜单树
Oct 22 Javascript
Firefox中使用outerHTML的2种解决方法
Jun 07 #Javascript
jQuery 顶部导航跟随滚动条滚动固定浮动在顶部
Jun 06 #Javascript
判断iframe里的页面是否加载完成
Jun 06 #Javascript
javascript获取隐藏元素(display:none)的高度和宽度的方法
Jun 06 #Javascript
js中的hasOwnProperty和isPrototypeOf方法使用实例
Jun 06 #Javascript
jquery数组过滤筛选方法grep()简介
Jun 06 #Javascript
js实现的标题栏新消息闪烁提示效果
Jun 06 #Javascript
You might like
PHP生成条形码大揭秘
2015/09/24 PHP
PHP接口并发测试的方法(推荐)
2016/12/15 PHP
mac os快速切换多个PHP版本的方法
2017/03/07 PHP
php支付宝系列之电脑网站支付
2018/05/30 PHP
php中html_entity_decode实现HTML实体转义
2018/06/13 PHP
浅谈thinkphp的nginx配置,以及重写隐藏index.php入口文件方法
2019/10/12 PHP
PHP如何防止用户重复提交表单
2020/12/09 PHP
一个可绑定数据源的jQuery数据表格插件
2010/07/17 Javascript
jquery 学习之二 属性 文本与值(text,val)
2010/11/25 Javascript
jquery中dom操作和事件的实例学习 仿yahoo邮箱登录框的提示效果
2011/11/30 Javascript
javascript模拟select,jselect的方法实现
2012/11/08 Javascript
window.requestAnimationFrame是什么意思,怎么用
2013/01/13 Javascript
JS获取时间的相关函数及时间戳与时间日期之间的转换
2016/02/04 Javascript
实例详解ECMAScript5中新增的Array方法
2016/04/05 Javascript
javascript实现列表切换效果
2016/05/02 Javascript
jQuery插件pagination实现无刷新分页
2016/05/21 Javascript
JS中的JSON对象的定义和取值实现代码
2018/05/09 Javascript
react native基于FlatList下拉刷新上拉加载实现代码示例
2018/09/30 Javascript
antd组件Upload实现自己上传的实现示例
2018/12/18 Javascript
微信小程序使用车牌号输入法的示例代码
2019/08/20 Javascript
详解JSON.stringify()的5个秘密特性
2020/05/26 Javascript
vue界面发送表情的实现代码
2020/09/11 Javascript
[44:22]完美世界DOTA2联赛循环赛 FTD vs PXG BO2第一场 11.01
2020/11/02 DOTA
python开发之for循环操作实例详解
2015/11/12 Python
听歌识曲--用python实现一个音乐检索器的功能
2016/11/15 Python
利用Python将每日一句定时推送至微信的实现方法
2018/08/13 Python
python K近邻算法的kd树实现
2018/09/06 Python
Python叠加两幅栅格图像的实现方法
2019/07/05 Python
python mysql断开重连的实现方法
2019/07/26 Python
Python多线程thread及模块使用实例
2020/04/28 Python
大学学年自我鉴定
2013/10/28 职场文书
运动会入场解说词300字
2014/01/25 职场文书
2014年学生会工作总结
2014/11/07 职场文书
英文版辞职信
2015/02/28 职场文书
golang elasticsearch Client的使用详解
2021/05/05 Golang
Java实现HTML转为Word的示例代码
2022/06/28 Java/Android