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 相关文章推荐
将HTML自动转为JS代码
Jun 26 Javascript
EasyUI 中 MenuButton 的使用方法
Jul 14 Javascript
jQuery实现点击标题输入详细信息
Apr 16 Javascript
jQuery操作Select的Option上下移动及移除添加等等
Nov 18 Javascript
深入学习JavaScript中的原型prototype
Aug 13 Javascript
举例讲解jQuery中可见性过滤选择器的使用
Apr 18 Javascript
Bootstrap开发实战之第一次接触Bootstrap
Jun 02 Javascript
Javascript之Math对象详解
Jun 07 Javascript
js a标签点击事件
Mar 30 Javascript
node.js中使用Export和Import的方法
Sep 18 Javascript
webstorm和.vue中es6语法报错的解决方法
May 08 Javascript
JavaScript 下载svg图片为png格式
Jun 21 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设计模式 Prototype (原型模式)代码
2011/06/26 PHP
android上传图片到PHP的过程详解
2015/08/03 PHP
Yii控制器中filter过滤器用法分析
2016/07/15 PHP
基于Laravel5.4实现多字段登录功能方法示例
2017/08/11 PHP
js控制div及网页相关属性的代码
2009/12/19 Javascript
简介JavaScript中substring()方法的使用
2015/06/06 Javascript
深入浅出 jQuery中的事件机制
2016/08/23 Javascript
Bootstrap标签页(Tab)插件使用方法
2017/03/21 Javascript
javascript中this用法实例详解
2017/04/06 Javascript
angularJS 发起$http.post和$http.get请求的实现方法
2017/05/18 Javascript
vue基于mint-ui的城市选择3级联动的示例
2017/10/25 Javascript
使用JS代码实现俄罗斯方块游戏
2018/08/03 Javascript
在Layui中实现开关按钮的效果实例
2019/09/29 Javascript
node.js中npm包管理工具用法分析
2020/02/14 Javascript
纯JS实现五子棋游戏
2020/05/28 Javascript
简单了解JavaScript arguement原理及作用
2020/05/28 Javascript
微信小程序开发(三):返回上一级页面并刷新操作示例【页面栈】
2020/06/01 Javascript
vue-cli3 引入 font-awesome的操作
2020/08/11 Javascript
[02:12]打造更好的电竞完美世界:完美盛典回顾篇
2018/12/19 DOTA
Python查询Mysql时返回字典结构的代码
2012/06/18 Python
Python中的列表知识点汇总
2015/04/14 Python
python实现一次创建多级目录的方法
2015/05/15 Python
解密Python中的描述符(descriptor)
2015/06/03 Python
python网络编程调用recv函数完整接收数据的三种方法
2017/03/31 Python
python实现简易数码时钟
2021/02/19 Python
PyQt5的安装配置过程,将ui文件转为py文件后显示窗口的实例
2019/06/19 Python
PyQt Qt Designer工具的布局管理详解
2019/08/07 Python
给我一面国旗 python帮你实现
2019/09/30 Python
详解pyinstaller selenium python3 chrome打包问题
2019/10/18 Python
利用纯css3实现的文字亮光特效的代码演示
2014/11/27 HTML / CSS
世界上最大的售后摩托车零配件超市:J&P Cycles
2017/12/08 全球购物
摩托车和ATV零件、配件和服装的首选在线零售商:MotoSport
2017/12/22 全球购物
轻松制作精彩视频:Animoto
2018/09/19 全球购物
房屋出租协议书范本(标准版)
2014/09/24 职场文书
铅球加油稿100字
2014/09/26 职场文书
Nginx URL重写rewrite机制原理及使用实例
2021/04/01 Servers