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 相关文章推荐
关于JavaScript的gzip静态压缩方法
Jan 05 Javascript
ExtJS 下拉多选框lovcombo
May 19 Javascript
javascript中方便增删改cookie的一个类
Oct 11 Javascript
jQuery判断多个input file 都不能为空的例子
Jun 23 Javascript
详细分析Javascript中创建对象的四种方式
Aug 17 Javascript
jQuery remove()过滤被删除的元素(推荐)
Jul 18 jQuery
js+css实现打字效果
Jun 24 Javascript
vue动态改变背景图片demo分享
Sep 13 Javascript
微信小程序之下拉列表实现方法解析(附完整源码)
Aug 23 Javascript
javascript/jquery实现点击触发事件的方法分析
Nov 11 jQuery
js 计算月/周的第一天和最后一天代码
Feb 01 Javascript
Antd-vue Table组件添加Click事件,实现点击某行数据教程
Nov 17 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
基于OpenCV的PHP图像人脸识别技术
2009/10/11 PHP
用C/C++扩展你的PHP 为你的php增加功能
2012/09/06 PHP
php上传文件中文文件名乱码的解决方法
2013/11/01 PHP
php上传功能集后缀名判断和随机命名(强力推荐)
2015/09/10 PHP
Yii编程开发常见调用技巧集锦
2016/07/15 PHP
PHP实现文件上传功能实例代码
2017/05/18 PHP
JavaScript在IE和Firefox(火狐)的不兼容问题解决方法小结
2010/04/13 Javascript
JavaScript 设计模式 安全沙箱模式
2010/09/24 Javascript
脚本合并提升javascript性能示例
2014/02/24 Javascript
jQuery实现返回顶部功能适合不支持js的浏览器
2014/08/19 Javascript
chrome浏览器当表单自动填充时如何去除浏览器自动添加的默认样式
2015/10/09 Javascript
jQuery插件扩展实例【添加回调函数】
2016/11/26 Javascript
Express进阶之log4js实用入门指南
2018/02/10 Javascript
完美解决iview 的select下拉框选项错位的问题
2018/03/02 Javascript
jQuery实现经典的网页3D轮播图封装功能【附源码下载】
2019/02/15 jQuery
JQuery的加载和选择器用法简单示例
2019/05/13 jQuery
Vue  webpack 项目自动打包压缩成zip文件的方法
2019/07/24 Javascript
js实现窗口全屏示例详解
2019/09/17 Javascript
[40:10]2015国际邀请赛全明星表演赛
2015/08/07 DOTA
java直接调用python脚本的例子
2014/02/16 Python
Python logging模块学习笔记
2014/05/24 Python
python用post访问restful服务接口的方法
2018/12/07 Python
对python 判断数字是否小于0的方法详解
2019/01/26 Python
Django框架模型简单介绍与使用分析
2019/07/18 Python
Python列表切片常用操作实例解析
2019/12/16 Python
tensorflow 20:搭网络,导出模型,运行模型的实例
2020/05/26 Python
Python字符串及文本模式方法详解
2020/09/10 Python
Pytorch之扩充tensor的操作
2021/03/04 Python
html5 canvas合成海报所遇问题及解决方案总结
2017/08/03 HTML / CSS
JD Sports马来西亚:英国领先的运动鞋和运动服饰零售商
2018/03/13 全球购物
Carmen Sol官网:购买果冻鞋、手袋和配件
2021/01/01 全球购物
经济管理专业毕业生自荐信范文
2014/01/02 职场文书
施工员岗位职责
2015/02/10 职场文书
锦旗赠语
2015/06/23 职场文书
Python离线安装openpyxl模块的步骤
2021/03/30 Python
SQL Server数据库的三种创建方法汇总
2023/05/08 MySQL