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 相关文章推荐
jQuery jqgrid 对含特殊字符json 数据的 Java 处理方法
Jan 01 Javascript
innerText和textContent对比及使用介绍
Feb 27 Javascript
javascript垃圾收集机制与内存泄漏详细解析
Nov 11 Javascript
js控制淡入淡出示例代码
Nov 12 Javascript
利用js正则表达式验证手机号,email地址,邮政编码
Jan 23 Javascript
json字符串之间的相互转换示例代码
Aug 21 Javascript
AngularJS基础 ng-mouseleave 指令详解
Aug 02 Javascript
微信小程序之绑定点击事件实例详解
Jul 07 Javascript
Vue-Cli中自定义过滤器的实现代码
Aug 12 Javascript
详解wow.js中各种特效对应的类名
Sep 13 Javascript
深入理解Vue2.x的虚拟DOM diff原理
Sep 27 Javascript
jQuery编写QQ简易聊天框
Aug 27 jQuery
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
基于mysql的论坛(2)
2006/10/09 PHP
让Nginx支持ThinkPHP的URL重写和PATHINFO的方法分享
2011/08/08 PHP
PHP取整数函数常用的四种方法小结
2012/07/05 PHP
PHP文件锁函数flock()详细介绍
2014/11/18 PHP
PHP之浮点数计算比较以及取整数不准确的解决办法
2015/07/29 PHP
总结PHP中DateTime的常用方法
2016/08/11 PHP
Laravel框架实现的记录SQL日志功能示例
2018/06/19 PHP
PHP pthreads v3下同步处理synchronized用法示例
2020/02/21 PHP
event对象的方法 兼容多浏览器
2009/06/27 Javascript
在Firefox下js select标签点击无法弹出
2014/03/06 Javascript
jQuery控制的不同方向的滑动(向左、向右滑动等)
2014/07/18 Javascript
javascript比较两个日期相差天数的方法
2015/07/24 Javascript
jquery+php随机生成红包金额数量代码分享
2015/08/27 Javascript
jQuery插件实现可输入和自动匹配的下拉框
2016/10/24 Javascript
jQuery插件FusionCharts实现的3D柱状图效果实例【附demo源码下载】
2017/03/03 Javascript
一份超级详细的Vue-cli3.0使用教程【推荐】
2018/11/15 Javascript
vue 子组件修改data或调用操作
2020/08/07 Javascript
vue-cli3自动消除console.log()的调试信息方式
2020/10/21 Javascript
[02:51]DOTA2英雄基础教程 风暴之灵
2013/12/23 DOTA
[56:45]DOTA2上海特级锦标赛D组小组赛#1 EG VS COL第一局
2016/02/28 DOTA
[28:57]EG vs VGJ.T 2018国际邀请赛小组赛BO2 第二场 8.16
2018/08/16 DOTA
python  Django中的apps.py的目的是什么
2018/10/15 Python
Python中常见的数制转换有哪些
2020/05/27 Python
python高级特性简介
2020/08/13 Python
python代码实现图书管理系统
2020/11/30 Python
迟到检讨书5000字
2014/01/31 职场文书
《孔子拜师》教学反思
2014/02/24 职场文书
遗嘱继承公证书
2014/04/09 职场文书
活动策划求职信模板
2014/04/21 职场文书
巴西世界杯32强口号
2014/06/05 职场文书
运动会广播稿50字-100字
2014/10/11 职场文书
2015年乡镇扶贫工作总结
2015/04/08 职场文书
小学教师个人工作总结2015
2015/04/20 职场文书
拾金不昧通报表扬范文
2015/05/05 职场文书
清明扫墓感想
2015/08/11 职场文书
Python first-order-model实现让照片动起来
2022/06/25 Python