您的位置:首页 > Web前端 > JQuery

jQuery源码学习笔记五(转)

2009-11-22 16:11 387 查看
在正式深入jQuery的核心功能选择器之前,还有一些方法,基本都是数组方法,用于遴选更具体的需要,如获得某个元素的所有祖选元素啦,等等。接着是其缓存机制data。

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.
});
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: