找回密码
 立即注册
首页 业界区 业界 javascript 缓存系统

javascript 缓存系统

龙正平 2025-5-29 15:06:18
模仿jQuery,设计了一个缓存系统。像jQuery.data这样的东西,Prototype与mootools也有,目的都是用来辅助事件系统,用来缓存其中生成的数据,而非缓存普通函数上次计算的结果。Prototype利用了它的Hash类,mootools没细看,它内部好像用来缓存uuid。一个共识是,为页面用到的元素设置uuid非常有用,要查找元素时,可以避免重复查找,也可以用于与事件回调函数相绑定。由于uuid目前只有IE支持,它叫做uniqueID,格式为ms__id\d+,后面的数字也有名堂,叫做uniqueNumber。jQuery那个算是uniqueNumber吧,而且它的缓存系统非常复杂,支持缓存单个数据(利用data这个读写方法)与一组数据(利用queue,删除用dequeue)。没办法,因为它是白手起家,没有像Prototype那样利用一个自定数据类型分担一下职责。是时候进入正题,说一下我的缓存系统了。它利用到我的超级数组对象,实现像queue与dequeue。但我的超级数组对象能做的事更多,像filter,forEach,map,reduce,one,toObject,contains,remove等一应俱全。
  1.    dom.eventTypes = dom.array(String("abort blur change click contextmenu  \
  2.                  dblclick error focus  keydown keypress keyup load mousedown  \
  3.                  mouseenter mouseup mouseleave mousemove mouseover mouseout \
  4.                  reset resize  select submit unload").match(/\w+/g));
  5.     //******************************缓存系统***********************
  6.     dom.mixin({
  7.         uuid : 0,
  8.         storage: {},
  9.         buildCache:function(item){
  10.             var key,cache = dom.storage;
  11.             //如果是window
  12.             if ( item.setInterval && ( item !== window && !item.frameElement )) {
  13.                 key =  "dom-window"
  14.             }else if(item.nodeType){
  15.                 if(!item.uuid){
  16.                     item.uuid = "dom" + dom.uuid++
  17.                     dom.cache("uuid","uuid-set",item);//保存元素的引用
  18.                 }//如果当前元素没有uuid这属性,那么为它添加一个      
  19.                 key =  item.uuid
  20.             }else if(dom.isString(item)){
  21.                 key =  item;
  22.             }else{
  23.                throw "item must be element node ,window or string"
  24.             }
  25.             if(!cache[key]){
  26.                 cache[key] = {};
  27.             }
  28.             return cache[key]
  29.         },
  30.         cache:function(item,name,data){//读写缓存
  31.             var cache = dom.buildCache(item);
  32.             if(data !== undefined){
  33.                 if(dom.isFunction(data)){//缓存函数,在函数设置一个uuid,生成方式取其toString()并去掉空白
  34.                     var uuid = (data+"").replace(/\s+/g,'');
  35.                     data.uuid = uuid;
  36.                 }
  37.                 if(!cache[name]){
  38.                     //set与list允许缓存一组数据,
  39.                     //其中如果带有-set后缀允许其中的元素重复,list则不允许
  40.                     if(/-set$/.test(name)){//如果是第一次存储
  41.                         cache[name] = array(data);
  42.                         cache[name].type = "set";
  43.                     }else if(/-list$/.test(name)){//
  44.                         cache[name] = array(data);
  45.                         cache[name].type = "list";
  46.                     }else{
  47.                         cache[name] = data;
  48.                     }
  49.                 }else{
  50.                     var type = cache[name].type;
  51.                     if(type && type === "set" ){
  52.                         cache[name].ensure(data)
  53.                     }else if(type && type === "list" ){
  54.                         cache[name].push(data)
  55.                     }else{
  56.                         cache[name] = data;
  57.                     }
  58.                 }
  59.                 return item;
  60.             }else{
  61.                 return cache[name]
  62.             }
  63.         },
  64.         //参数可以为1,2,3
  65.         removeCache:function(item,name,data){
  66.             if(!arguments.length) return;
  67.             var cache = dom.buildCache(item),isDOM = !!item.nodeType;
  68.             if(isDOM && dom.eventTypes.contains(name)){
  69.                 name = name + "-handlers-list";
  70.             };
  71.             if(arguments.length === 3){//移除指定的data
  72.                 if(cache[name] instanceof dom.array && cache[name].length > 0){
  73.                     //对于由事件绑定函数构成的超级数组,我们在缓存它的时候为每个函数设置了一个uuid
  74.                     //现在我们比较现在传入的函数的uuid与超级数组中的某个元素的uuid是否相等
  75.                     //如果有我们将得它的引用,有了它我们才能使用remove方法移除它。
  76.                     if(dom.isFunction(data)){
  77.                         var uuid = (data+"").replace(/\s+/g,''),
  78.                         fn = cache[name].one(function(fn){
  79.                             return fn.uuid == uuid;
  80.                         });
  81.                         if(fn){
  82.                             cache[name].remove(fn);
  83.                         }
  84.                     }else{
  85.                         cache[name].remove(data);
  86.                     }                  
  87.                     if(cache[name].length === 0)
  88.                         dom.removeCache(item,name);
  89.                 }else{
  90.                     dom.removeCache(item,name);
  91.                 }
  92.             }else if(arguments.length === 2){//移除条目
  93.                 delete cache[name]
  94.                 if(!dom.isExtensible(cache)){
  95.                     dom.removeCache(item);
  96.                 }
  97.             }else {
  98.                 delete cache;
  99.                 if(isDOM){
  100.                     dom.removeCache("uuid","uuid-set",item);
  101.                     dom.removeAttr(item,"uuid");
  102.                 }
  103.             }
  104.         },
  105.         clearCache:function(){
  106.             var cache = dom.buildCache("uuid","uuid-set");
  107.             if(!cache) return;//如果为空直接返回
  108.             cache.forEach(function(el){
  109.                 dom.removeAttr(el,"uuid");
  110.             });
  111.             dom.storage = null;
  112.         }
  113.     });
复制代码
buildCache是用于在dom.storage上开辟一个命名空间,cache用于在命名空间存储各种数据,可以为单个数据,一组数据,一组数据又分为list与set两种,区别是允许元素是否重复,重复的list相重于jQuery.queue设置的数组。对于window对象的处理,jQuery是在闭包内搞了一个windowData,我则它为在dom.storage开辟了一个名为dom-window的空间。removeCache相当于jQuery.removeData与jQuery.unquere,但功能还要强大,能根据传入参数的个数选用不同的功能。clearCache则直接删除所有缓存。
值得注意的是,在IE中为DOM元素设置私有属性会引起内存泄漏,所有在页面unload时需要手动去除它们。各大类库也是这样做了,dom.cache("uuid","uuid-set",item)就是用于unload时取出所有设置过uuid的元素,一一去掉其uuid。不过实际上,调用clearCache方法就可以了。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册