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中confirm,alert,prompt函数使用区别分析
Apr 01 Javascript
utf-8编码引起js输出中文乱码的解决办法
Jun 23 Javascript
javascript取消文本选定的实现代码
Nov 14 Javascript
Ext对基本类型的扩展 ext,extjs,format
Dec 25 Javascript
javascript简单判断输入内容是否合法的方法
May 11 Javascript
新入门node.js必须要知道的概念(必看篇)
Aug 10 Javascript
JavaScript 限制文本框不可输入英文单双引号的方法
Dec 20 Javascript
vue实现百度搜索下拉提示功能实例
Jun 14 Javascript
[js高手之路]图解javascript的原型(prototype)对象,原型链实例
Aug 28 Javascript
jQuery判断自定义属性data-val用法示例
Jan 07 jQuery
vue 通过绑定事件获取当前行的id操作
Jul 27 Javascript
Vue提供的三种调试方式你知道吗
Jan 18 Vue.js
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压缩多个CSS为一个css的代码并缓存
2011/04/21 PHP
PHP连接和操作MySQL数据库基础教程
2014/09/29 PHP
php使用标签替换的方式生成静态页面
2015/05/21 PHP
CI(CodeIgniter)框架中URL特殊字符处理与SQL注入隐患分析
2019/02/28 PHP
ExtJS扩展 垂直tabLayout实现代码
2009/06/21 Javascript
基于jquery的获取mouse坐标插件的实现代码
2010/04/01 Javascript
javascript常用方法、属性集合及NodeList 和 HTMLCollection 的浏览器差异
2010/12/25 Javascript
jquery 模板的应用示例
2013/11/12 Javascript
jquery动态改变onclick属性导致失效的问题解决方法
2013/12/04 Javascript
js怎么判断flash swf文件是否加载完毕
2014/08/14 Javascript
JavaScript实现生成GUID(全局统一标识符)
2014/09/05 Javascript
原生js和jquery实现图片轮播特效
2015/04/23 Javascript
jQuery中设置form表单中action值的实现方法
2016/05/25 Javascript
js事件驱动机制 浏览器兼容处理方法
2016/07/23 Javascript
jQuery基本选择器之标签名选择器
2016/09/03 Javascript
JS监控关闭浏览器操作的实例详解
2017/09/12 Javascript
详解vue-cli之webpack3构建全面提速优化
2017/12/25 Javascript
layer iframe 设置关闭按钮的方法
2019/09/12 Javascript
一篇文章带你浅入webpack的DLL优化打包
2020/02/20 Javascript
Python内置函数bin() oct()等实现进制转换
2012/12/30 Python
浅析Python中元祖、列表和字典的区别
2016/08/17 Python
浅谈用Python实现一个大数据搜索引擎
2017/11/28 Python
Python对List中的元素排序的方法
2018/04/01 Python
Python学习笔记之图片人脸检测识别实例教程
2019/03/06 Python
Python中numpy模块常见用法demo实例小结
2019/03/16 Python
pytorch masked_fill报错的解决
2020/02/18 Python
Python使用Excel将数据写入多个sheet
2020/05/16 Python
UI自动化定位常用实现方法代码示例
2020/10/27 Python
python反扒机制的5种解决方法
2021/02/06 Python
使用 CSS3 中@media 实现网页自适应的示例代码
2020/03/24 HTML / CSS
劳资专员岗位职责
2013/12/27 职场文书
体检通知范文
2015/04/21 职场文书
村党组织公开承诺书
2015/04/30 职场文书
歌咏比赛主持词
2015/06/29 职场文书
会议主持词结束语
2015/07/03 职场文书
2016年习主席讲话学习心得体会
2016/01/20 职场文书