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 相关文章推荐
让Firefox支持event对象实现代码
Nov 07 Javascript
基于Jquery的动态创建DOM元素的代码
Dec 28 Javascript
jquery解析JSON数据示例代码
Mar 17 Javascript
jquery中获得元素尺寸和坐标的方法整理
May 18 Javascript
node.js中的buffer.length方法使用说明
Dec 14 Javascript
Javascript中的方法链(Method Chaining)介绍
Mar 15 Javascript
JavaScript 函数的执行过程
May 09 Javascript
利用fecha进行JS日期处理
Nov 21 Javascript
JS开发中百度地图+城市联动实现实时触发查询地址功能
Apr 13 Javascript
微信小程序实现给循环列表添加点击样式实例
Apr 26 Javascript
JavaScript学习笔记之惰性函数示例详解
Aug 27 Javascript
element上传组件循环引用及简单时间倒计时的实现
Oct 01 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
浅谈ThinkPHP的URL重写
2014/11/25 PHP
PHP中使用curl入门教程
2015/07/02 PHP
yii2使用ajax返回json的实现方法
2016/05/14 PHP
Yii2组件之多图上传插件FileInput的详细使用教程
2016/06/20 PHP
thinkphp验证码的实现(form、ajax实现验证)
2016/07/28 PHP
cakephp常见知识点汇总
2017/02/24 PHP
php封装db类连接sqlite3数据库的方法实例
2017/12/19 PHP
PHP实现动态删除XML数据的方法示例
2018/03/30 PHP
用js生产批量批处理执行命令
2008/07/28 Javascript
JavaScript学习笔记(十)
2010/01/17 Javascript
JavaScript 以对象为索引的关联数组
2010/05/19 Javascript
JavaScript结合AJAX_stream实现流式显示
2015/01/08 Javascript
JavaSciprt中处理字符串之sup()方法的使用教程
2015/06/08 Javascript
jQuery插件datalist实现很好看的input下拉列表
2015/07/14 Javascript
详解JavaScript节流函数中的Throttle
2016/07/16 Javascript
以v-model与promise两种方式实现vue弹窗组件
2018/05/21 Javascript
解决vue props 拿不到值的问题
2018/09/11 Javascript
微信小程序实现保存图片到相册功能
2018/11/30 Javascript
vue-cli3+typescript新建一个项目的思路分析
2019/08/06 Javascript
Vue快速实现通用表单验证的示例代码
2020/01/09 Javascript
[01:09:40]Newbee vs Pain 2018国际邀请赛小组赛BO2 第一场 8.16
2018/08/17 DOTA
在漏洞利用Python代码真的很爽
2007/08/26 Python
Python脚本实现自动发带图的微博
2016/04/27 Python
深入理解Python单元测试unittest的使用示例
2017/11/18 Python
python爬取内容存入Excel实例
2019/02/20 Python
pyQT5 实现窗体之间传值的示例
2019/06/20 Python
python实现DEM数据的阴影生成的方法
2019/07/23 Python
使用IPython或Spyder将省略号表示的内容完整输出
2020/04/20 Python
Python实现CAN报文转换工具教程
2020/05/05 Python
让Django的BooleanField支持字符串形式的输入方式
2020/05/20 Python
python 求两个向量的顺时针夹角操作
2021/03/04 Python
急诊科护士自我鉴定
2013/10/14 职场文书
党校培训思想汇报
2013/12/30 职场文书
大学三年计划书范文
2014/04/30 职场文书
人事专员岗位职责
2015/02/03 职场文书
2015年试用期自我评价范文
2015/03/10 职场文书