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 相关文章推荐
制作特殊字的脚本
Jun 26 Javascript
在javascript中对于DOM的加强
Apr 11 Javascript
一个简单的动态加载js和css的jquery代码
Sep 01 Javascript
详解JavaScript函数对象
Nov 15 Javascript
在其他地方你学不到的jQuery小贴士和技巧(欢迎收藏)
Jan 20 Javascript
ES6的新特性概览
Mar 10 Javascript
JS组件Bootstrap Select2使用方法解析
May 30 Javascript
jQuery电话号码验证实例
Jan 05 Javascript
vue2+el-menu实现路由跳转及当前项的设置方法实例
Nov 07 Javascript
详解javascript replace高级用法
Feb 17 Javascript
react 生命周期实例分析
May 18 Javascript
JavaScript实现音乐播放器
Aug 14 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
windows下zendframework项目环境搭建(通过命令行配置)
2012/12/06 PHP
PHP循环函数使用介绍之PHP基础入门教程
2013/09/21 PHP
支持生僻字且自动识别utf-8编码的php汉字转拼音类
2014/06/27 PHP
简单谈谈favicon
2015/06/10 PHP
php分享朋友圈的实现代码
2019/02/18 PHP
限制文本字节数js代码
2007/03/06 Javascript
Jquery知识点三 jquery表单对象操作
2011/01/17 Javascript
23个Javascript弹出窗口特效整理
2011/02/25 Javascript
jqplot通过ajax动态画折线图的方法及思路
2013/12/08 Javascript
Egret引擎开发指南之编译项目
2014/09/03 Javascript
JS函数arguments数组获得实际传参数个数的实现方法
2016/05/28 Javascript
js求数组中全部数字可拼接出的最大整数示例代码
2017/08/25 Javascript
ajax请求+vue.js渲染+页面加载的示例
2018/02/11 Javascript
Vue Promise的axios请求封装详解
2018/08/13 Javascript
vue+Element实现搜索关键字高亮功能
2019/05/28 Javascript
Webpack中loader打包各种文件的方法实例
2019/09/03 Javascript
JS实现水平移动与垂直移动动画
2019/12/19 Javascript
vue element-ui实现input输入框金额数字添加千分位
2019/12/29 Javascript
python 异常处理总结
2016/10/18 Python
听歌识曲--用python实现一个音乐检索器的功能
2016/11/15 Python
Python3调用微信企业号API发送文本消息代码示例
2017/11/10 Python
解决Python 中英文混输格式对齐的问题
2018/07/16 Python
python编写简易聊天室实现局域网内聊天功能
2018/07/28 Python
Python 图像处理: 生成二维高斯分布蒙版的实例
2019/07/04 Python
python实现连连看辅助之图像识别延伸
2019/07/17 Python
Pycharm使用远程linux服务器conda/python环境在本地运行的方法(图解))
2019/12/09 Python
女性时尚网购:Chic Me
2019/07/30 全球购物
军训自我鉴定
2014/01/22 职场文书
法律专业学生的自我评价
2014/02/07 职场文书
暑期社会实践感言
2014/02/25 职场文书
大学四年个人自我小结
2014/03/05 职场文书
给公司的建议书范文
2014/05/13 职场文书
大学生先进个人主要事迹材料
2015/11/04 职场文书
纪检干部学习心得体会
2016/01/23 职场文书
创业计划书之奶茶店开店方案范本!
2019/08/06 职场文书
忆童年!用Python实现愤怒的小鸟游戏
2021/06/07 Python