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 相关文章推荐
JS刷新当前页面的几种方法总结
Dec 24 Javascript
jquery获得keycode的示例代码
Dec 30 Javascript
jQuery内部原理和实现方式浅析
Feb 03 Javascript
javascript学习小结之prototype
Dec 03 Javascript
Javascript数组Array方法解读
Mar 13 Javascript
纯js实现瀑布流布局及ajax动态新增数据
Apr 07 Javascript
AngularJS指令与控制器之间的交互功能示例
Dec 14 Javascript
Vue的百度地图插件尝试使用
Sep 06 Javascript
详解基于Vue+Koa的pm2配置
Oct 24 Javascript
jQuery zTree搜索-关键字查询 递归无限层功能实现代码
Jan 25 jQuery
5分钟学会Vue动画效果(小结)
Jul 21 Javascript
vue实现一个6个输入框的验证码输入组件功能的实例代码
Jun 29 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
ASP知识讲座四
2006/10/09 PHP
PHP获取网址的顶级域名函数代码
2012/09/24 PHP
php的mkdir()函数创建文件夹比较安全的权限设置方法
2014/07/28 PHP
php使用lua+redis实现限流,计数器模式,令牌桶模式
2019/04/04 PHP
打开超链需要“确认”对话框的方法
2007/03/08 Javascript
快速解决jQuery与其他库冲突的方法介绍
2014/01/02 Javascript
JavaScript中判断原生函数检查function是否是原生代码
2014/09/09 Javascript
JavaScript中的数值范围介绍
2014/12/29 Javascript
使用javascript提交form表单方法汇总
2015/06/25 Javascript
JavaScript简单修改窗口大小的方法
2015/08/03 Javascript
浅谈javascript的Touch事件
2015/09/27 Javascript
深入解析AngularJS框架中$scope的作用与生命周期
2016/03/05 Javascript
详谈jQuery中的一些正则匹配表达式
2017/03/08 Javascript
js获取json中key所对应的value值的简单方法
2020/06/17 Javascript
AngularJS读取JSON及XML文件的方法示例
2017/05/25 Javascript
jQuery中 DOM节点操作方法大全
2017/10/12 jQuery
解决vue 引入子组件报错的问题
2018/09/06 Javascript
angularjs实现table表格td单元格单击变输入框/可编辑状态示例
2019/02/21 Javascript
vue-cli3 DllPlugin 提取公用库的方法
2019/04/24 Javascript
微信小程序 拍照或从相册选取图片上传代码实例
2019/08/28 Javascript
python使用pyhook监控键盘并实现切换歌曲的功能
2014/07/18 Python
python批量修改文件名的实现代码
2014/09/01 Python
python 出现SyntaxError: non-keyword arg after keyword arg错误解决办法
2017/02/14 Python
Python实现 多进程导入CSV数据到 MySQL
2017/02/26 Python
对python3 中方法各种参数和返回值详解
2018/12/15 Python
django使用haystack调用Elasticsearch实现索引搜索
2019/07/24 Python
解决django无法访问本地static文件(js,css,img)网页里js,cs都加载不了
2020/04/07 Python
解决django 向mysql中写入中文字符出错的问题
2020/05/18 Python
Python定时任务APScheduler原理及实例解析
2020/05/30 Python
耐克美国官网:Nike.com
2016/08/01 全球购物
Hotels.com韩国:海外国内旅行所需的酒店和住宿预订网站
2020/05/08 全球购物
static关键字的用法
2013/10/07 面试题
大学生入党思想汇报
2014/01/01 职场文书
大型活动组织方案
2014/05/10 职场文书
Django+Celery实现定时任务的示例
2021/06/23 Python
Python帮你解决手机qq微信内存占用太多问题
2022/02/15 Python