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 相关文章推荐
彪哥1.1(智能表格)提供下载
Sep 07 Javascript
点击页面其它地方隐藏该div的两种思路
Nov 18 Javascript
js获取当前地址 JS获取当前URL的示例代码
Feb 26 Javascript
js实现按钮加背景图片常用方法
Nov 01 Javascript
一款基于jQuery的图片场景标注提示弹窗特效
Jan 05 Javascript
JavaScript实现同一页面内两个表单互相传值的方法
Aug 12 Javascript
JavaScript每天必学之事件
Sep 18 Javascript
利用Node.js+Koa框架实现前后端交互的方法
Feb 27 Javascript
从零开始学习Node.js系列教程之基于connect和express框架的多页面实现数学运算示例
Apr 13 Javascript
零基础之Node.js搭建API服务器的详解
Mar 08 Javascript
浅谈vue加载优化策略
Mar 19 Javascript
给原生html中添加水印遮罩层的实现示例
Apr 02 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的简易冒泡法代码分享
2012/08/28 PHP
Drupal7中常用的数据库操作实例
2014/03/02 PHP
php 数组随机取值的简单实例
2016/05/23 PHP
php静态成员方法和静态的成员属性的使用方法
2017/10/26 PHP
TP5框架实现签到功能的方法分析
2020/04/05 PHP
jQuery创建平滑的页面滚动(顶部或底部)
2013/02/26 Javascript
jQuery写的日历(包括日历的样式及功能)
2013/04/23 Javascript
给应用部分的js代码设定一个统一的入口
2014/06/15 Javascript
Javascript 拖拽的一些高级的应用(逐行分析代码,让你轻松了拖拽的原理)
2015/01/23 Javascript
详解javascript高级定时器
2015/12/31 Javascript
JavaScript弹出对话框的三种方式
2016/03/23 Javascript
JS获取当前使用的浏览器名字以及版本号实现方法
2016/08/19 Javascript
bootstrap 点击空白处popover弹出框隐藏实例
2018/01/24 Javascript
echarts鼠标覆盖高亮显示节点及关系名称详解
2018/03/17 Javascript
webpack开发环境和生产环境的深入理解
2018/11/08 Javascript
vue-cli脚手架打包静态资源请求出错的原因与解决
2019/06/06 Javascript
在Vuex中Mutations修改状态操作
2020/07/24 Javascript
Vue 防止短时间内连续点击后多次触发请求的操作
2020/11/11 Javascript
swiperjs实现导航与tab页的联动
2020/12/13 Javascript
Python中的defaultdict模块和namedtuple模块的简单入门指南
2015/04/01 Python
详解Tensorflow数据读取有三种方式(next_batch)
2018/02/01 Python
Python Pandas找到缺失值的位置方法
2018/04/12 Python
解决tensorflow模型参数保存和加载的问题
2018/07/26 Python
python 工具 字符串转numpy浮点数组的实现
2020/03/14 Python
Python startswith()和endswith() 方法原理解析
2020/04/28 Python
python2.7使用scapy发送syn实例
2020/05/05 Python
Eagle Eyes Optics鹰眼光学:高性能太阳镜
2018/12/07 全球购物
东南亚排名第一的服务市场:kaodim
2019/03/28 全球购物
HolidayLettings英国:预订最好的度假公寓、别墅和自助式住宿
2019/08/27 全球购物
如何使用PHP session
2015/04/21 面试题
前台文员岗位职责
2013/12/28 职场文书
欢迎领导标语
2014/06/27 职场文书
大学生军训自我鉴定范文
2014/09/18 职场文书
2014幼儿教师个人工作总结
2014/12/03 职场文书
2014幼儿园班主任工作总结
2014/12/04 职场文书
2015年高校保卫处工作总结
2015/07/23 职场文书