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 相关文章推荐
网页自动刷新,不产生嗒嗒声的一个解决方法
Mar 27 Javascript
关于火狐(firefox)及ie下event获取的两种方法
Dec 27 Javascript
JavaScript实现网页图片等比例缩放实现代码及调用方式
Feb 25 Javascript
javascript确认框的三种使用方法
Dec 17 Javascript
JavaScript语言对Unicode字符集的支持详解
Dec 30 Javascript
Angular.js跨controller实现参数传递的两种方法
Feb 20 Javascript
jQuery插件FusionCharts绘制的2D双柱状图效果示例【附demo源码】
May 13 jQuery
关于vue.js组件数据流的问题
Jul 26 Javascript
React-Native左右联动List的示例代码
Sep 21 Javascript
webuploader实现上传图片到服务器功能
Aug 16 Javascript
Vue 莹石摄像头直播视频实例代码
Aug 31 Javascript
微信小程序自定义波浪组件使用方法详解
Sep 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
拼音码表的生成
2006/10/09 PHP
php将数组转换成csv格式文件输出的方法
2015/03/14 PHP
PHP连接MSSQL方法汇总
2016/02/05 PHP
php 输出缓冲 Output Control用法实例详解
2020/03/03 PHP
php设计模式之迭代器模式实例分析【星际争霸游戏案例】
2020/04/07 PHP
JavaScript ( (__ = !$ + $)[+$] + ({} + $)[_/_] +({} + $)[_/_] )
2011/02/25 Javascript
javascript 数组排序函数sort和reverse使用介绍
2013/11/21 Javascript
深入理解JavaScript系列(29):设计模式之装饰者模式详解
2015/03/03 Javascript
js滑动提示效果代码分享
2016/03/10 Javascript
使用JavaScript解决网页图片拉伸问题(推荐)
2016/11/25 Javascript
js实现获取鼠标当前的位置
2016/12/14 Javascript
jQuery展示表格点击变色、全选、删除
2017/01/05 Javascript
js使用i18n实现页面国际化的方法
2017/05/09 Javascript
Vue.js中组件中的slot实例详解
2017/07/17 Javascript
Webstorm2016使用技巧(SVN插件使用)
2018/10/29 Javascript
基于vue2的canvas时钟倒计时组件步骤解析
2018/11/05 Javascript
elementUI vue this.$confirm 和el-dialog 弹出框 移动 示例demo
2019/07/03 Javascript
layui下拉列表select实现可输入查找的方法
2019/09/28 Javascript
Python3遍历目录树实现方法
2015/05/22 Python
基于wxpython开发的简单gui计算器实例
2015/05/30 Python
详解使用python的logging模块在stdout输出的两种方法
2017/05/17 Python
python虚拟环境迁移方法
2019/01/03 Python
python实现五子棋小游戏
2020/03/25 Python
python2.7 安装pip的方法步骤(管用)
2019/05/05 Python
python判断链表是否有环的实例代码
2020/01/31 Python
Python判断变量是否是None写法代码实例
2020/10/09 Python
详解css position 5种不同的值的用法
2019/07/30 HTML / CSS
最好的商品表达自己:Cafepress
2019/09/04 全球购物
卡拉威高尔夫官方网站:Callaway Golf
2020/09/16 全球购物
类、抽象类、接口的差异
2016/06/13 面试题
上海雨人软件技术开发有限公司测试题
2015/07/14 面试题
博士生入学考试推荐信
2013/11/17 职场文书
优秀共产党员先进事迹材料
2014/05/06 职场文书
欢迎横幅标语
2014/06/17 职场文书
《曹冲称象》教学反思
2016/02/20 职场文书
Nginx部署vue项目和配置代理的问题解析
2021/08/04 Servers