昨晚在cssrain网站上看到了一篇关于jQuery的data函数的介绍(《学做jQuery中的data()函数》),看了博主仿写的data函数,之后又查看了jQuery源码中的data的实现方式,都基本一个原理:给DOM元素添加自定义属性来储存唯一的id作为找到该值的索引,再储存到一个对象字面量里。又看了下MooTools中关于store函数的实现方式,也都是给DOM元素添加自定义属性的方式。
我就在想了,通过给DOM元素添加属性的方式来储存临时值能有什么好处呢?有必要这样吗?一方面这样增加了DOM元素的属性数目,增加了操作DOM元素的负荷,如果是在需要在该DOM元素上大量储存临时值的时候,这将会是很大的性能消耗(Douglas Crockford说过:DOM API非常低效且令人费解,运行程序的最大开销往往是DOM而非javascrpt。—摘自《高性能网站建设进阶指南》)。所以,尽量保持DOM元素的简洁,在某些情况下能使得性能有所改观。我想 ,这样是实现方式,一方面是为了语意化的原因吧:把临时值存到指定的DOM元素里,之后通过该DOM元素取回临时值。
昨晚自己也开始思索怎么不使用DOM元素的情况下来实现储存临时值的方式。其实,这个需求的实现方式是比较多的,而比较容易想到的方式还是通过对象字面量的方式,下面是我第一个实现方案:
[javascript]
var Data=(function(){
var _set=function(name,value){
if(!_set.cache){
_set.cache={
uids:{},
value:{}
};
}
var _uDate=""+(new Date()).getTime(),
_uids=_set["cache"]["uids"];
if(!_uids[name]){
_uids[name]=_uDate;
}
_set["cache"]["value"][name+_uids[name]]=value;
}
var _get=function(name){
return _set["cache"]["value"][name+_set["cache"]["uids"][name]];
}
var _remove=function(name){
delete _set["cache"]["value"][name+_set["cache"]["uids"][name]];
delete _set["cache"]["uids"][name];
}
return {
set:_set,
get:_get,
remove:_remove
}
})();
[/javascript]
但是,上面的实现方式有一个需求不能够满足:但每次的name相同的时候,需要把每一次的临时值都储存起来,而不是覆盖掉。从这点出发,改写了上面的代码:
[javascript]
var Data=(function(){
var _set=function(name,value,override){
if(!_set.cache){
_set.cache={
uids:{},
value:{}
};
}
override = override || false;
var _uDate=""+(new Date()).getTime(),
_uids=_set["cache"]["uids"],
_val=_set["cache"]["value"];
/*
* 如果在_uids中还没有name这个子元素,则表明是第一次使用这个变量
* 否则,将_uids[name]转换成对象字面量的形式,用来储存每次name相同的时候的值
*/
if(!_uids[name]){
_uids[name]=_uDate;
_val[name]=value;
}else{
//如果要覆盖原来的值
if(override){
_uids[name]=_uDate;
_val[name]=value;
}else{
//如果是第一次重复了name值,则将第一次储存的name的值,储存为以name为对象字面量的第一个子元素的键值对
if(typeof _uids[name] !== "object"){
var temp=_uids[name];
_uids[name]={};
_uids[name]["uuid"]=-1;
_uids[name][name+(++_uids[name]["uuid"])]=temp;
temp=_val[name];
_val[name]={};
_val[name][name+_uids[name]["uuid"]]=temp;
}
//储存
var _uuid=_uids[name]["uuid"];
_uids[name][name+(++_uuid)]=_uDate;
_val[name][name+_uuid]=value;
}
}
}
var _get=function(name){
return _set["cache"]["value"][name];
}
var _remove=function(name){
delete _set["cache"]["value"][name];
delete _set["cache"]["uids"][name];
}
return {
set:_set,
get:_get,
remove:_remove
}
})();
//Usage:
Data.set("supersha","shafeng");
Data.set("supersha","change my name");
Data.set("supersha","change again");
Data.set("supersha","change once again");
for(var key in Data.get("supersha")){
alert(Data.get("supersha")[key]);
}
Data.set("shafeng","shanpeng");
alert(Data.get("shafeng"));
[/javascript]
这次通过一个override的参数来指定是否覆盖相同name的临时值,默认是不覆盖。但是为了实现这两个需求,代码也长了许多了。
衡量无处不在。。。