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 相关文章推荐
web页面数据展示新想法(json)
Jun 08 Javascript
Eclipse编辑jsp、js文件时卡死现象的解决办法汇总
Feb 02 Javascript
Vuejs第十三篇之组件——杂项
Sep 09 Javascript
利用angular.copy取消变量的双向绑定与解析
Nov 25 Javascript
Bootstrap3 图片(响应式图片&amp;图片形状)
Jan 04 Javascript
解决vue中无法动态修改jqgrid组件 url地址的问题
Mar 01 Javascript
jQuery简单实现的HTML页面文本框模糊匹配查询功能完整示例
May 09 jQuery
原生JS实现的简单轮播图功能【适合新手】
Aug 17 Javascript
最适应的vue.js的form提交涉及多种插件【推荐】
Aug 27 Javascript
微信小程序学习笔记之文件上传、下载操作图文详解
Mar 29 Javascript
再也不怕 JavaScript 报错了,怎么看怎么处理都在这儿
Dec 09 Javascript
vue使用echarts画组织结构图
Feb 06 Vue.js
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
虫族 ZERG 概述
2020/03/14 星际争霸
不错的一篇面向对象的PHP开发模式(简写版)
2007/03/15 PHP
ThinkPHP自动验证失败的解决方法
2011/06/09 PHP
Laravel 5框架学习之Eloquent 关系
2015/04/09 PHP
PHP文件操作之获取目录下文件与计算相对路径的方法
2016/01/08 PHP
PHP设计模式之建造者模式(Builder)原理与用法案例详解
2019/12/12 PHP
JavaScript的Function详细
2006/11/14 Javascript
js中的push和join方法使用介绍
2013/10/08 Javascript
如何判断鼠标是否在DIV的区域内
2013/11/13 Javascript
jQuery实现div随意拖动的实例代码(通用代码)
2016/01/28 Javascript
浅析jQuery 3.0中的Data
2016/06/14 Javascript
基于JavaScript实现单选框下拉菜单添加文件效果
2016/06/26 Javascript
JavaScript编写一个简易购物车功能
2016/09/17 Javascript
JS 终止执行的实现方法
2016/11/24 Javascript
vue.js 图片上传并预览及图片更换功能的实现代码
2018/08/27 Javascript
JavaScript数组去重的几种方法
2019/04/07 Javascript
vue+render+jsx实现可编辑动态多级表头table的实例代码
2020/04/01 Javascript
[00:34]DOTA2上海特级锦标赛 VG战队宣传片
2016/03/04 DOTA
[37:45]完美世界DOTA2联赛PWL S3 LBZS vs Phoenix 第二场 12.09
2020/12/11 DOTA
python 控制语句
2011/11/03 Python
python模块restful使用方法实例
2013/12/10 Python
Python验证码识别处理实例
2015/12/28 Python
基于Python数据可视化利器Matplotlib,绘图入门篇,Pyplot详解
2017/10/13 Python
Python WSGI的深入理解
2018/08/01 Python
解决Django加载静态资源失败的问题
2019/07/28 Python
python基于pdfminer库提取pdf文字代码实例
2019/08/15 Python
python 在右键菜单中加入复制目标文件的有效存放路径(单斜杠或者双反斜杠)
2020/04/08 Python
anaconda3安装及jupyter环境配置全教程
2020/08/24 Python
python pip如何手动安装二进制包
2020/09/30 Python
京东全球售:直邮香港,澳门,台湾,美国,澳大利亚等地区
2017/09/24 全球购物
Clearly澳大利亚:购买眼镜、太阳镜和隐形眼镜
2018/04/26 全球购物
澳大利亚在线生活方式商店:Mytopia
2018/07/08 全球购物
linux面试题参考答案(7)
2012/10/29 面试题
清明节演讲稿
2014/05/27 职场文书
2014标准社保办理委托书
2014/10/06 职场文书
2015年餐厅服务员工作总结
2015/04/23 职场文书