javascript 缓存系统

原创|其它|编辑:郝浩|2009-12-30 10:41:52.000|阅读 726 次

概述:模仿jQuery,设计了一个缓存系统。像jQuery.data这样的东西,Prototype与mootools也有,目的都是用来辅助事件系统,用来缓存其中生成的数据,而非缓存普通函数上次计算的结果。Prototype利用了它的Hash类,mootools没细看,它内部好像用来缓存uuid。一个共识是,为页面用到的元素设置uuid非常有用,要查找元素时,可以避免重复查找,也可以用于与事件回调函数相绑定。

# 界面/图表报表/文档/IDE等千款热门软控件火热销售中 >>

模仿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等一应俱全。

001.dom.eventTypes = dom.array(String("abort blur change click contextmenu  \
002.              dblclick error focus  keydown keypress keyup load mousedown  \
003.              mouseenter mouseup mouseleave mousemove mouseover mouseout \
004.              reset resize  select submit unload").match(/\w+/g));
005. //******************************缓存系统***********************
006. dom.mixin({
007.     uuid : 0,
008.     storage: {},
009.     buildCache:function(item){
010.         var key,cache = dom.storage;
011.         //如果是window
012.         if ( item.setInterval && ( item !== window && !item.frameElement )) {
013.             key =  "dom-window"
014.         }else if(item.nodeType){
015.             if(!item.uuid){
016.                 item.uuid = "dom" + dom.uuid++
017.                 dom.cache("uuid","uuid-set",item);//保存元素的引用
018.             }//如果当前元素没有uuid这属性,那么为它添加一个      
019.             key =  item.uuid
020.         }else if(dom.isString(item)){
021.             key =  item;
022.         }else{
023.            throw "item must be element node ,window or string"
024.         }
025.         if(!cache[key]){
026.             cache[key] = {};
027.         }
028.         return cache[key]
029.     },
030.     cache:function(item,name,data){//读写缓存
031.         var cache = dom.buildCache(item);
032.         if(data !== undefined){
033.             if(dom.isFunction(data)){//缓存函数,在函数设置一个uuid,生成方式取其toString()并去掉空白
034.                 var uuid = (data+"").replace(/\s+/g,'');
035.                 data.uuid = uuid;
036.             }
037.             if(!cache[name]){
038.                 //set与list允许缓存一组数据,
039.                 //其中如果带有-set后缀允许其中的元素重复,list则不允许
040.                 if(/-set$/.test(name)){//如果是第一次存储
041.                     cache[name] = array(data);
042.                     cache[name].type = "set";
043.                 }else if(/-list$/.test(name)){//
044.                     cache[name] = array(data);
045.                     cache[name].type = "list";
046.                 }else{
047.                     cache[name] = data;
048.                 }
049.             }else{
050.                 var type = cache[name].type;
051.                 if(type && type === "set" ){
052.                     cache[name].ensure(data)
053.                 }else if(type && type === "list" ){
054.                     cache[name].push(data)
055.                 }else{
056.                     cache[name] = data;
057.                 }
058.             }
059.             return item;
060.         }else{
061.             return cache[name]
062.         }
063.     },
064.     //参数可以为1,2,3
065.     removeCache:function(item,name,data){
066.         if(!arguments.length) return;
067.         var cache = dom.buildCache(item),isDOM = !!item.nodeType;
068.         if(isDOM && dom.eventTypes.contains(name)){
069.             name = name + "-handlers-list";
070.         };
071.         if(arguments.length === 3){//移除指定的data 
072.             if(cache[name] instanceof dom.array && cache[name].length > 0){
073.                 //对于由事件绑定函数构成的超级数组,我们在缓存它的时候为每个函数设置了一个uuid
074.                 //现在我们比较现在传入的函数的uuid与超级数组中的某个元素的uuid是否相等
075.                 //如果有我们将得它的引用,有了它我们才能使用remove方法移除它。
076.                 if(dom.isFunction(data)){
077.                     var uuid = (data+"").replace(/\s+/g,''),
078.                     fn = cache[name].one(function(fn){
079.                         return fn.uuid == uuid;
080.                     });
081.                     if(fn){
082.                         cache[name].remove(fn);
083.                     }
084.                 }else{
085.                     cache[name].remove(data);
086.                 }                  
087.                 if(cache[name].length === 0)
088.                     dom.removeCache(item,name);
089.             }else{
090.                 dom.removeCache(item,name);
091.             }
092.         }else if(arguments.length === 2){//移除条目
093.             delete cache[name]
094.             if(!dom.isExtensible(cache)){
095.                 dom.removeCache(item);
096.             }
097.         }else {
098.             delete cache;
099.             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方法就可以了。


标签:

本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@evget.com

文章转载自:博客园

为你推荐

  • 推荐视频
  • 推荐活动
  • 推荐产品
  • 推荐文章
  • 慧都慧问
扫码咨询


添加微信 立即咨询

电话咨询

客服热线
023-68661681

TOP