jQuery源码学习笔记五(转)
2009-11-22 16:11
387 查看
在正式深入jQuery的核心功能选择器之前,还有一些方法,基本都是数组方法,用于遴选更具体的需要,如获得某个元素的所有祖选元素啦,等等。接着是其缓存机制data。
接着下来看jQuery的缓存机制,jQuery的性能很大部分依仗于它。
001.
//去除两边的空白
002.
trim:
function
(text){
003.
return
(text||
""
).replace(/^\s+|\s+$/g,
""
);
004.
},
005.
//转换成数组,很大众的方法
006.
makeArray:
function
(array){
007.
var
ret=[];
008.
if
(array!=
null
){
009.
var
i=array.length;
010.
//Thewindow,strings(andfunctions)alsohave'length'
011.
if
(i==
null
||
typeof
array===
"string"
||jQuery.isFunction(array)||array.setInterval)
012.
ret[0]=array;
//就只有一元素
013.
else
014.
while
(i)
//处理数组
015.
ret[--i]=array[i];
016.
}
017.
return
ret;
018.
},
019.
//判断是否在数组中,类似indexOf
020.
inArray:
function
(elem,array){
021.
for
(
var
i=0,length=array.length;i<length;i++)
022.
//Use===becauseonIE,window==document
023.
if
(array[i]===elem)
024.
return
i;
025.
return
-1;
026.
},
027.
//把新元素或第二个数组加入第一个数组中
028.
//类似数组的concat
029.
merge:
function
(first,second){
030.
//WehavetoloopthiswaybecauseIE&Operaoverwritethelength
031.
//expandoofgetElementsByTagName
032.
var
i=0,elem,pos=first.length;
033.
//Also,weneedtomakesurethatthecorrectelementsarebeingreturned
034.
//(IEreturnscommentnodesina'*'query)
035.
if
(!jQuery.support.getAll){
036.
while
((elem=second[i++])!=
null
)
037.
if
(elem.nodeType!=8)
038.
first[pos++]=elem;
039.
}
else
040.
while
((elem=second[i++])!=
null
)
041.
first[pos++]=elem;
042.
return
first;
043.
},
044.
//过滤重复元素,用done这个普通对象做过滤器(因为键如果同名将被覆盖掉)
045.
unique:
function
(array){
046.
var
ret=[],done={};
047.
try
{
048.
for
(
var
i=0,length=array.length;i<length;i++){
049.
var
id=jQuery.data(array[i]);
050.
if
(!done[id]){
051.
done[id]=
true
;
052.
ret.push(array[i]);
053.
}
054.
}
055.
}
catch
(e){
056.
ret=array;
057.
}
058.
return
ret;
059.
},
060.
//类似数组的filter,这方法起得真不好,通常这都是与正则有关的……
061.
//$.grep([0,1,2],function(n,i){
062.
//returnn>0;
063.
//});
064.
//[1,2]
065.
grep:
function
(elems,callback,inv){
066.
var
ret=[];
067.
//Gothroughthearray,onlysavingtheitems
068.
//thatpassthevalidatorfunction
069.
//写法很特别,callback之前的!是为了防止回调函数没有返回值
070.
//javascript默认没有返回值的函数都返回undefined,这样一搞
071.
//就变成true,原来返回true的变成false,我们需要负负得正,中和一下
072.
//于是!=出场了,而inv也是未必存在的,用!强制转换成布尔
073.
for
(
var
i=0,length=elems.length;i<length;i++)
074.
if
(!inv!=!callback(elems[i],i))
075.
ret.push(elems[i]);
076.
return
ret;
077.
},
078.
//就是数组中的map
079.
map:
function
(elems,callback){
080.
var
ret=[];
081.
//Gothroughthearray,translatingeachoftheitemstotheir
082.
//newvalue(orvalues).
083.
for
(
var
i=0,length=elems.length;i<length;i++){
084.
var
value=callback(elems[i],i);
085.
if
(value!=
null
)
086.
ret[ret.length]=value;
087.
}
088.
return
ret.concat.apply([],ret);
089.
}
090.
});
091.
//jQuery.browser下面的方法已经被废弃了,这些都是为兼容以前的版本与插件用
092.
var
userAgent=navigator.userAgent.toLowerCase();
093.
//Figureoutwhatbrowserisbeingused
094.
jQuery.browser={
095.
version:(userAgent.match(/.+(?:rv|it|ra|ie)[\/:]([\d.]+)/)||[0,
'0'
])[1],
096.
safari:/webkit/.test(userAgent),
097.
opera:/opera/.test(userAgent),
098.
msie:/msie/.test(userAgent)&&!/opera/.test(userAgent),
099.
mozilla:/mozilla/.test(userAgent)&&!/(compatible|webkit)/.test(userAgent)
100.
};
101.
//把以下方法parent,parents,next……添加到jQuery的原型上去,都是一些过滤方法
102.
jQuery.each({
103.
parent:
function
(elem){
return
elem.parentNode;},
104.
parents:
function
(elem){
return
jQuery.dir(elem,
"parentNode"
);},
105.
next:
function
(elem){
return
jQuery.nth(elem,2,
"nextSibling"
);},
106.
prev:
function
(elem){
return
jQuery.nth(elem,2,
"previousSibling"
);},
107.
nextAll:
function
(elem){
return
jQuery.dir(elem,
"nextSibling"
);},
108.
prevAll:
function
(elem){
return
jQuery.dir(elem,
"previousSibling"
);},
109.
siblings:
function
(elem){
return
jQuery.sibling(elem.parentNode.firstChild,elem);},
110.
children:
function
(elem){
return
jQuery.sibling(elem.firstChild);},
111.
contents:
function
(elem){
return
jQuery.nodeName(elem,
"iframe"
)?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}
112.
},
function
(name,fn){
113.
jQuery.fn[name]=
function
(selector){
//方法体
114.
var
ret=jQuery.map(
this
,fn);
115.
if
(selector&&
typeof
selector==
"string"
)
116.
ret=jQuery.multiFilter(selector,ret);
117.
return
this
.pushStack(jQuery.unique(ret),name,selector);
118.
};
119.
});
120.
//把以下方法appendTo,prependTo,insertBefore……添加到jQuery的原型上去,
121.
//利用已有的append,prepend……方法构建
122.
jQuery.each({
123.
appendTo:
"append"
,
124.
prependTo:
"prepend"
,
125.
insertBefore:
"before"
,
126.
insertAfter:
"after"
,
127.
replaceAll:
"replaceWith"
128.
},
function
(name,original){
129.
jQuery.fn[name]=
function
(selector){
130.
var
ret=[],insert=jQuery(selector);
131.
for
(
var
i=0,l=insert.length;i<l;i++){
132.
var
elems=(i>0?
this
.clone(
true
):
this
).get();
133.
jQuery.fn[original].apply(jQuery(insert[i]),elems);
134.
ret=ret.concat(elems);
135.
}
136.
return
this
.pushStack(ret,name,selector);
137.
};
138.
});
139.
//一些重要常用的静态方法
140.
jQuery.each({
141.
removeAttr:
function
(name){
142.
jQuery.attr(
this
,name,
""
);
143.
if
(
this
.nodeType==1)
144.
this
.removeAttribute(name);
145.
},
146.
addClass:
function
(classNames){
147.
jQuery.className.add(
this
,classNames);
148.
},
149.
removeClass:
function
(classNames){
150.
jQuery.className.remove(
this
,classNames);
151.
},
152.
toggleClass:
function
(classNames,state){
153.
if
(
typeof
state!==
"boolean"
)
154.
state=!jQuery.className.has(
this
,classNames);
155.
jQuery.className[state?
"add"
:
"remove"
](
this
,classNames);
156.
},
157.
remove:
function
(selector){
158.
if
(!selector||jQuery.filter(selector,[
this
]).length){
159.
//Preventmemoryleaks
160.
jQuery(
"*"
,
this
).add([
this
]).each(
function
(){
161.
jQuery.event.remove(
this
);
//★★★★★
162.
jQuery.removeData(
this
);
163.
});
164.
if
(
this
.parentNode)
165.
this
.parentNode.removeChild(
this
);
166.
}
167.
},
168.
empty:
function
(){
169.
//Removeelementnodesandpreventmemoryleaks
170.
jQuery(
this
).children().remove();
171.
//Removeanyremainingnodes
172.
while
(
this
.firstChild)
173.
this
.removeChild(
this
.firstChild);
174.
}
175.
},
function
(name,fn){
176.
jQuery.fn[name]=
function
(){
177.
return
this
.each(fn,arguments);
178.
};
179.
});
180.
//将带单位的数值去掉单位
181.
//Helperfunctionusedbythedimensionsandoffsetmodules
182.
function
num(elem,prop){
183.
return
elem[0]&&parseInt(jQuery.curCSS(elem[0],prop,
true
),10)||0;
184.
}
接着下来看jQuery的缓存机制,jQuery的性能很大部分依仗于它。
001.
var
expando=
"jQuery"
+now(),uuid=0,windowData={};
002.
jQuery.extend({
003.
cache:{},
004.
data:
function
(elem,name,data){
005.
//坚决不染指window
006.
elem=elem==window?
007.
windowData:
008.
elem;
009.
//在elem上设置一个变量
010.
var
id=elem[expando];
011.
//ComputeauniqueIDfortheelement
012.
if
(!id)
013.
//同时为id,elem[expando]赋值,值为单一数字
014.
id=elem[expando]=++uuid;
015.
//Onlygeneratethedatacacheifwe're
016.
//tryingtoaccessormanipulateit
017.
if
(name&&!jQuery.cache[id])
018.
//在jQuery.cache上开辟一个对象,专门用于储存与那个elem有关的东西
019.
jQuery.cache[id]={};
020.
//Preventoverridingthenamedcachewithundefinedvalues
021.
if
(data!==undefined)
//data必须定义
022.
jQuery.cache[id][name]=data;
023.
//Returnthenamedcachedata,ortheIDfortheelement
024.
//根据第二个参数是否存在决定返回的是缓存数据还是element的特别ID
025.
return
name?
026.
jQuery.cache[id][name]:
027.
id;
028.
},
029.
//移除缓存数据
030.
removeData:
function
(elem,name){
031.
elem=elem==window?
032.
windowData:
033.
elem;
034.
var
id=elem[expando];
035.
//Ifwewanttoremoveaspecificsectionoftheelement'sdata
036.
if
(name){
037.
if
(jQuery.cache[id]){
038.
//Removethesectionofcachedata
039.
delete
jQuery.cache[id][name];
040.
//Ifwe'veremovedallthedata,removetheelement'scache
041.
name=
""
;
042.
for
(name
in
jQuery.cache[id])
043.
break
;
044.
if
(!name)
045.
jQuery.removeData(elem);
046.
}
047.
//Otherwise,wewanttoremovealloftheelement'sdata
048.
}
else
{
049.
//Cleanuptheelementexpando
050.
try
{
051.
//IE不能直接用delete去移除,要用removeAttribute
052.
delete
elem[expando];
053.
}
catch
(e){
054.
//IEhastroubledirectlyremovingtheexpando
055.
//butit'sokwithusingremoveAttribute
056.
if
(elem.removeAttribute)
057.
elem.removeAttribute(expando);
058.
}
059.
//Completelyremovethedatacache
060.
//用缓存体中把其索引值也移掉
061.
delete
jQuery.cache[id];
062.
}
063.
},
064.
//缓存元素的类组数属性
065.
//可读写
066.
queue:
function
(elem,type,data){
067.
if
(elem){
068.
type=(type||
"fx"
)+
"queue"
;
069.
var
q=jQuery.data(elem,type);
070.
if
(!q||jQuery.isArray(data))
071.
//q是数组
072.
q=jQuery.data(elem,type,jQuery.makeArray(data));
073.
else
if
(data)
074.
q.push(data);
075.
}
076.
return
q;
077.
},
078.
//对元素的类数组缓存进行dequeue(也就是shift)
079.
dequeue:
function
(elem,type){
080.
var
queue=jQuery.queue(elem,type),
081.
fn=queue.shift();
082.
if
(!type||type===
"fx"
)
083.
fn=queue[0];
084.
if
(fn!==undefined)
085.
fn.call(elem);
086.
}
087.
});
088.
//让jQuery对象也能获得这种缓存能力
089.
//都是用上面静态方法实现,最终的缓存体还是jQuery.cache
090.
jQuery.fn.extend({
091.
data:
function
(key,value){
092.
var
parts=key.split(
"."
);
093.
parts[1]=parts[1]?
"."
+parts[1]:
""
;
094.
if
(value===undefined){
095.
var
data=
this
.triggerHandler(
"getData"
+parts[1]+
"!"
,[parts[0]]);
096.
if
(data===undefined&&
this
.length)
097.
data=jQuery.data(
this
[0],key);
098.
return
data===undefined&&parts[1]?
099.
this
.data(parts[0]):
100.
data;
101.
}
else
102.
return
this
.trigger(
"setData"
+parts[1]+
"!"
,[parts[0],value]).each(
function
(){
103.
jQuery.data(
this
,key,value);
104.
});
105.
},
106.
removeData:
function
(key){
107.
return
this
.each(
function
(){
108.
jQuery.removeData(
this
,key);
109.
});
110.
},
111.
queue:
function
(type,data){
112.
if
(
typeof
type!==
"string"
){
113.
data=type;
114.
type=
"fx"
;
115.
}
116.
if
(data===undefined)
117.
return
jQuery.queue(
this
[0],type);
118.
return
this
.each(
function
(){
119.
var
queue=jQuery.queue(
this
,type,data);
120.
if
(type==
"fx"
&&queue.length==1)
121.
queue[0].call(
this
);
122.
});
123.
},
124.
dequeue:
function
(type){
125.
return
this
.each(
function
(){
126.
jQuery.dequeue(
this
,type);
127.
});
128.
}
129.
});
相关文章推荐
- jQuery源码研究分析学习笔记-回调函数(11)
- jquery源码学习笔记1
- jQuery源码研究分析学习笔记-jQuery.deferred()(12)
- jquery 2.0.3 源码学习笔记(三)类数组
- jQuery源码研究分析学习笔记-jQuery.extend()、jQuery.fn.extend()(八)
- jQuery源码研究分析学习笔记-静态方法和属性(10)
- jquery源码学习笔记
- 2016年11月2日——jQuery源码学习笔记
- jQuery源码学习笔记(05)
- jQuery源码学习笔记(09)
- jQuery源码学习笔记:构造jQuery对象
- jQuery源码研究分析学习笔记-jQuery.fn.init()(五)
- jQuery源码学习笔记一(转)
- 2016年11月1日——jQuery源码学习笔记
- 菜鸟的jQuery源码学习笔记(一)
- jquery源码学习笔记三:jQuery工厂剖析
- jQuery源码学习笔记一
- jQuery源码研究分析学习笔记-jQuery.buildFragment()(六)
- jquery 2.0.3 源码学习笔记(三)构造器
- jQuery源码学习笔记:jQuery.fn.init(selector,context,rootjQuery)代码详解