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下用层来实现select的title提示属性
Feb 23 Javascript
jQuery EasyUI API 中文文档 DateTimeBox日期时间框
Oct 16 Javascript
基于jquery的代码显示区域自动拉长效果
Dec 07 Javascript
JQuery获取浏览器窗口内容部分高度的代码
Feb 24 Javascript
各浏览器中querySelector和querySelectorAll的实现差异分析
May 23 Javascript
javascript中的undefined和not defined区别示例介绍
Feb 26 Javascript
我的Node.js学习之路(一)
Jul 06 Javascript
AngularJS基础 ng-keypress 指令简单示例
Aug 02 Javascript
AngularJs中Bootstrap3 datetimepicker使用实例
Dec 13 Javascript
webpack+vue中使用别名路径引用静态图片地址
Nov 20 Javascript
layui点击导航栏刷新tab页的示例代码
Aug 14 Javascript
解决betterScroll在vue中存在图片时,出现拉不动的问题
Sep 27 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安全配置
2006/12/06 PHP
PHP5 面向对象(学习记录)
2009/12/02 PHP
解析php中的fopen()函数用打开文件模式说明
2013/06/20 PHP
PHP在线调试执行的实现方法(附demo源码)
2016/04/28 PHP
JQuery Easyui Tree的oncheck事件实现代码
2010/05/28 Javascript
js判断undefined类型示例代码
2014/02/10 Javascript
jQuery实现可用于博客的动态滑动菜单
2015/03/09 Javascript
EasyUI在表单提交之前进行验证的实例代码
2016/06/24 Javascript
详解本地Node.js服务器作为api服务器的解决办法
2017/02/28 Javascript
JS常用的几种数组遍历方式以及性能分析对比实例详解
2018/04/11 Javascript
使用JavaScript实现node.js中的path.join方法
2018/08/12 Javascript
js序列化和反序列化的使用讲解
2019/01/19 Javascript
Vue结合后台导入导出Excel问题详解
2019/02/19 Javascript
JavaScript 函数用法详解【函数定义、参数、绑定、作用域、闭包等】
2020/05/12 Javascript
JavaScript如何使用插值实现图像渐变
2020/06/28 Javascript
Python存取XML的常见方法实例分析
2017/03/21 Python
TensorFlow实现AutoEncoder自编码器
2018/03/09 Python
python读取一个目录下所有txt里面的内容方法
2018/06/23 Python
python networkx 包绘制复杂网络关系图的实现
2019/07/10 Python
Python如何用wx模块创建文本编辑器
2020/06/07 Python
python3.6.8 + pycharm + PyQt5 环境搭建的图文教程
2020/06/11 Python
浅谈matplotlib 绘制梯度下降求解过程
2020/07/12 Python
Python3爬虫中关于中文分词的详解
2020/07/29 Python
Python 常用日期处理 -- calendar 与 dateutil 模块的使用
2020/09/02 Python
如何基于python实现年会抽奖工具
2020/10/20 Python
Python为何不支持switch语句原理详解
2020/10/21 Python
Python 实现一个简单的web服务器
2021/01/03 Python
希尔顿酒店中国网站:Hilton中国
2017/03/11 全球购物
Kent & Curwen:与大卫·贝克汉姆合作
2017/06/13 全球购物
英国最大的笔记本电脑直销专家:Laptops Direct
2019/07/20 全球购物
eBay奥地利站:eBay.at
2019/07/24 全球购物
银行奉献演讲稿
2014/09/16 职场文书
公司党的群众路线教育实践活动领导班子对照检查材料
2014/09/25 职场文书
如何用Node.js编写内存效率高的应用程序
2021/04/30 Javascript
MySQL 四种连接和多表查询详解
2021/07/16 MySQL
关于pytest结合csv模块实现csv格式的数据驱动问题
2022/05/30 Python