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 相关文章推荐
网络之美 JavaScript中Get和Set访问器的实现代码
Sep 19 Javascript
JavaScript 原型继承
Dec 26 Javascript
jQuery.each()用法分享
Jul 31 Javascript
jQuery中parent()方法用法实例
Jan 07 Javascript
jquery验证手机号是否正确实例讲解
Nov 17 Javascript
浅析jQuery操作select控件的取值和设值
Dec 07 Javascript
jQuery插件form-validation-engine正则表达式操作示例
Feb 09 Javascript
原生JS实现不断变化的标签
May 22 Javascript
详解Angular-cli生成组件修改css成less或sass的实例
Jul 27 Javascript
利用JavaScript实现栈的数据结构示例代码
Aug 02 Javascript
详解js跨域请求的两种方式,支持post请求
May 05 Javascript
如何封装了一个vue移动端下拉加载下一页数据的组件
Jan 06 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
玛琪朵 Macchiato
2021/03/03 咖啡文化
刚才在简化php的库,结果发现很多东西
2006/12/31 PHP
PHP中通过fopen()函数访问远程文件示例
2014/11/18 PHP
SharePoint 客户端对象模型 (一) ECMA Script
2011/05/22 Javascript
Prototype源码浅析 String部分(二)
2012/01/16 Javascript
你需要知道的10个最佳javascript开发实践小结
2012/04/15 Javascript
在jQuery中 关于json空对象筛选替换
2013/04/15 Javascript
Function.prototype.call.apply结合用法分析示例
2013/07/03 Javascript
检查输入的是否是数字使用keyCode配合onkeypress事件
2014/01/23 Javascript
Javascript 拖拽的一些简单的应用(逐行分析代码,让你轻松了拖拽的原理)
2015/01/23 Javascript
基于AngularJs + Bootstrap + AngularStrap相结合实现省市区联动代码
2016/05/30 Javascript
关于数据与后端进行交流匹配(点亮星星)
2016/08/03 Javascript
JavaScript自动点击链接 防止绕过浏览器访问的方法
2017/01/19 Javascript
轻松学习Javascript闭包
2017/03/01 Javascript
vue渲染时闪烁{{}}的问题及解决方法
2018/03/28 Javascript
js对象数组和对象的使用实例详解
2019/08/27 Javascript
node.js使用http模块创建服务器和客户端完整示例
2020/02/10 Javascript
详解Python中的文本处理
2015/04/11 Python
python结合shell查询google关键词排名的实现代码
2016/02/27 Python
用matplotlib画等高线图详解
2017/12/14 Python
在dataframe两列日期相减并且得到具体的月数实例
2018/07/03 Python
python输出100以内的质数与合数实例代码
2018/07/08 Python
Python反射和内置方法重写操作详解
2018/08/27 Python
Jupyter Notebook打开任意文件夹操作
2020/04/14 Python
解决Django Haystack全文检索为空的问题
2020/05/19 Python
css3新增颜色表示方式分享
2014/04/15 HTML / CSS
俄罗斯GamePark游戏商店网站:购买游戏、游戏机和配件
2020/03/13 全球购物
寄语是什么意思
2014/04/10 职场文书
大班幼儿评语大全
2014/04/30 职场文书
国际贸易专业自荐信
2014/06/10 职场文书
个人安全生产责任书
2014/07/28 职场文书
助残日活动总结
2014/08/27 职场文书
销售会议开幕词
2015/01/28 职场文书
任长霞观后感
2015/06/16 职场文书
2016年五四青年节校园广播稿
2015/12/17 职场文书
Python干货实战之八音符酱小游戏全过程详解
2021/10/24 Python