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

jQuery源码学习笔记三(转)

2009-11-22 16:09 489 查看
还有一点,jQuery.prototype第一个阶级的能力部署就完成了。就像一个茧,jQuery对象包裹着一个或复数个DOM对象,jQuery对象的能力来自其prototype,而其prototype的方法则是jQuery.prototype的一个副本。

01.
//对当前jQuery中的DOM进行slice操作,并把参数传入this.prevObject中

02.
slice:
function
(){

03.
return
this
.pushStack(Array.prototype.slice.apply(
this
,arguments),

04.
"slice"
,Array.prototype.slice.call(arguments).join(
","
));

05.
},

06.
//与上面差不多

07.
map:
function
(callback){

08.
return
this
.pushStack(jQuery.map(
this
,
function
(elem,i){

09.
return
callback.call(elem,i,elem);

10.
}));

11.
},

12.
//把之前放入this.preveObject的DOM数组取出来,加入现在的DOM数组中

13.
andSelf:
function
(){

14.
return
this
.add(
this
.prevObject);

15.
},

16.

17.
domManip:
function
(args,table,callback){

18.
if
(
this
[0]){

19.
//如果jQuery对象有DOM元素,则取得其文档对象,调用其createDocumentFragment方法

20.
var
fragment=(
this
[0].ownerDocument||
this
[0]).createDocumentFragment(),

21.
//这里的args恒为arguments对象,用jQuery.clean获得纯DOM元素数组

22.
scripts=jQuery.clean(args,(
this
[0].ownerDocument||
this
[0]),fragment),

23.
first=fragment.firstChild;

24.

25.
if
(first)

26.
for
(
var
i=0,l=
this
.length;i<l;i++)

27.
//callback传入一个元素与一个文档

28.
callback.call(root(
this
[i],first),
this
.length>1||i>0?

29.
fragment.cloneNode(
true
):fragment);

30.
if
(scripts)

31.
jQuery.each(scripts,evalScript);

32.
}

33.

34.
return
this
;

35.
//root用于检测当前元素是否为table,是就检测tbody是否存在,没有则创建

36.
function
root(elem,cur){

37.
return
table&&jQuery.nodeName(elem,
"table"
)&&jQuery.nodeName(cur,
"tr"
)?

38.
(elem.getElementsByTagName(
"tbody"
)[0]||

39.
elem.appendChild(elem.ownerDocument.createElement(
"tbody"
))):

40.
elem;

41.
}

42.
}

43.
};

44.
//把jQuery.prototype的能力加持到jQuery.prototype.init.prototype上

45.
jQuery.fn.init.prototype=jQuery.fn;

至此,jQuery对象第一阶级的能力就告一段落,要不对象体就很长。下面添加新的能力时就用jQuery.extend求添加,就像Prototype的Object.extend,mootool的Native.implement,Base2的Base.extend,Ext的apply,凡此种种,把一个属性包或独立的方法名与方法体作为参数加入目标对象中。因为光是在对象体搞(这里是原型),没有私有变量可言,有时我们很需要这些作为胶水在连接我们的方法,因此打散写有打散写的好处。更何况,jQuery类库都是整个包围在一个闭包中,这些散乱的函数与变量不会逃逸到外面去,与我们的业务逻辑中用的函数或变量发生命名冲突。

01.
//jQuery的能力扩展的核心函数

02.
//这要求存在继承者与授与者两方,一般来说继承者在左,授与者在右,授与者通常是一个简单的属性包

03.
jQuery.extend=jQuery.fn.extend=
function
(){

04.
//copyreferencetotargetobject

05.
var
target=arguments[0]||{},i=1,length=arguments.length,deep=
false
,options;

06.
//Handleadeepcopysituation

07.
if
(
typeof
target===
"boolean"
){
//如果第一个参数是布尔值

08.
deep=target;

09.
target=arguments[1]||{};
//设置继承者

10.
//skipthebooleanandthetarget

11.
i=2;

12.
}

13.
//Handlecasewhentargetisastringorsomething(possibleindeepcopy)

14.
if
(
typeof
target!==
"object"
&&!jQuery.isFunction(target))

15.
target={};

16.
//如果没有指定要继承能力的对象,则扩展到自身

17.
//extendjQueryitselfifonlyoneargumentispassed

18.
if
(length==i){

19.
target=
this
;

20.
--i;

21.
}

22.
for
(;i<length;i++)

23.
//Onlydealwithnon-null/undefinedvalues

24.
if
((options=arguments[i])!=
null
)

25.
//Extendthebaseobject

26.
for
(
var
name
in
options){

27.
var
src=target[name],copy=options[name];

28.

29.
//Preventnever-endingloop

30.
if
(target===copy)

31.
continue
;

32.
//如果是深复制,某对象的属性也是对象并且不是HTMLElement,则把它逐一分解拷到继承者

33.
//Recurseifwe'remergingobjectvalues

34.
if
(deep&©&&
typeof
copy===
"object"
&&!copy.nodeType)

35.
target[name]=jQuery.extend(deep,

36.
//Nevermoveoriginalobjects,clonethem

37.
src||(copy.length!=
null
?[]:{})

38.
,copy);

39.
//Don'tbringinundefinedvalues

40.
else
if
(copy!==undefined)

41.
target[name]=copy;

42.
}

43.
//Returnthemodifiedobject

44.
return
target;

45.
};

定义几个位于闭包的顶层变量,准备新一轮的功能扩展

1.
//excludethefollowingcsspropertiestoaddpx

2.
//将转换成px单位

3.
var
exclude=/z-?index|font-?weight|opacity|zoom|line-?height/i,

4.
//cachedefaultView

5.
defaultView=document.defaultView||{},

6.
toString=Object.prototype.toString;


001.
//第二轮能力扩展,这次是添加一系列静态方法

002.
jQuery.extend({

003.

004.
noConflict:
function
(deep){

005.
//引入jQuery类库后,闭包外面的window.$与window.jQuery都储存着一个函数,

006.
//它是用来生成jQuery对象或在domReady后执行里面的函数的

007.
//回顾最上面的代码,在还没有把function赋给它们时,_jQuery与_$已经被赋值了,

008.
//因此它们俩的值一定必然是undefined

009.
//因此这种放弃控制权的技术很简单,就是用undefined把window.$里面的jQuery系的函数清除掉

010.
//这时Prototype或mootools的$就可以明门正娶了

011.
window.$=_$;
//相当window.$=undefined

012.
//如果连你的程序也有一个叫jQuery的东西呢,jQuery可以大方地连这个也让渡出去

013.
//这时就要为noConflict添加一个布尔值,为true

014.
if
(deep)

015.
//但我们必须用一个东西要接纳jQuery对象与jQuery的入口函数

016.
//闭包里面的东西除非被window等宿主对象引用,否则就是不可见的

017.
//因此我们把闭包里面的jQueryreturn出去,外面用一个变量接纳就是

018.
window.jQuery=_jQuery;
//相当window.jQuery=undefined

019.
return
jQuery;

020.
},

021.

022.
//外国近年来新发现的检测技术toString

023.
isFunction:
function
(obj){

024.
return
toString.call(obj)===
"[objectFunction]"
;

025.
},

026.

027.
isArray:
function
(obj){

028.
return
toString.call(obj)===
"[objectArray]"
;

029.
},

030.

031.
//checkifanelementisina(orisan)XMLdocument

032.
//检测是否为XML的文档对象

033.
isXMLDoc:
function
(elem){

034.
return
elem.nodeType===9&&elem.documentElement.nodeName!==
"HTML"
||

035.
!!elem.ownerDocument&&jQuery.isXMLDoc(elem.ownerDocument);

036.
},

037.

038.
//Evalulatesascriptinaglobalcontext

039.
//把一段文本解析成脚本,利用script元素的text属性

040.
globalEval:
function
(data){

041.
if
(data&&/\S/.test(data)){

042.
//InspiredbycodebyAndreaGiammarchi

043.
//http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html

044.
var
head=document.getElementsByTagName(
"head"
)[0]||document.documentElement,

045.
script=document.createElement(
"script"
);

046.
//自行创建一个script元素,如果支持text属性则直接赋,不支持就用标准方法在里面添加文本

047.
script.type=
"text/javascript"
;

048.
if
(jQuery.support.scriptEval)

049.
script.appendChild(document.createTextNode(data));

050.
else

051.
script.text=data;

052.
//UseinsertBeforeinsteadofappendChildtocircumventanIE6bug.

053.
//Thisariseswhenabasenodeisused(#2709).

054.
head.insertBefore(script,head.firstChild);

055.
head.removeChild(script);

056.
}

057.
},

058.
//检测elem的nodeName是否等于第二个参数name

059.
nodeName:
function
(elem,name){

060.
return
elem.nodeName&&elem.nodeName.toUpperCase()==name.toUpperCase();

061.
},

062.
//argsisforinternalusageonly

063.
each:
function
(object,callback,args){

064.
var
name,i=0,length=object.length;

065.

066.
if
(args){

067.
if
(length===undefined){

068.
//如果是对象就对其值调用方法,如果调用函数没有返回值或返回false就跳出循环

069.
for
(name
in
object)

070.
if
(callback.apply(object[name],args)===
false
)

071.
break
;

072.
}
else

073.
//如果是数组

074.
for
(;i<length;)

075.
if
(callback.apply(object[i++],args)===
false
)

076.
break
;

077.
//同上,只不过没有传入第三个参数

078.
//Aspecial,fast,caseforthemostcommonuseofeach

079.
}
else
{

080.
if
(length===undefined){

081.
for
(name
in
object)

082.
if
(callback.call(object[name],name,object[name])===
false
)

083.
break
;

084.
}
else

085.
for
(
var
value=object[0];

086.
i<length&&callback.call(value,i,value)!==
false
;value=object[++i]){}

087.
}

088.

089.
return
object;

090.
},

091.
//用于返回各种属性

092.
prop:
function
(elem,value,type,i,name){

093.
//Handleexecutablefunctions

094.
if
(jQuery.isFunction(value))

095.
value=value.call(elem,i);

096.

097.
//HandlepassinginanumbertoaCSSproperty

098.
return
typeof
value===
"number"
&&type==
"curCSS"
&&!exclude.test(name)?

099.
value+
"px"
:

100.
value;

101.
},

接着下来就是对样式的操作了,样式在WEB开发中非常重要,我留在下一节重点讲!

转自:http://www.cnblogs.com/rubylouvre/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: