jquery是一個(gè)輕量級(jí)的JS框架,這點(diǎn)相信大部分人都聽(tīng)過(guò),而jquery之所以有這樣一個(gè)稱(chēng)呼,就是因?yàn)樗那呐艘患庖拢瑢⒆约航o隱藏了起來(lái)。
創(chuàng)新互聯(lián)專(zhuān)注為客戶(hù)提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于成都網(wǎng)站建設(shè)、成都網(wǎng)站制作、渾南網(wǎng)絡(luò)推廣、微信小程序定制開(kāi)發(fā)、渾南網(wǎng)絡(luò)營(yíng)銷(xiāo)、渾南企業(yè)策劃、渾南品牌公關(guān)、搜索引擎seo、人物專(zhuān)訪、企業(yè)宣傳片、企業(yè)代運(yùn)營(yíng)等,從售前售中售后,我們都將竭誠(chéng)為您服務(wù),您的肯定,是我們最大的嘉獎(jiǎng);創(chuàng)新互聯(lián)為所有大學(xué)生創(chuàng)業(yè)者提供渾南建站搭建服務(wù),24小時(shí)服務(wù)熱線:18982081108,官方網(wǎng)址:www.cdcxhl.com
//以下截取自jquery源碼片段(function( window, undefined ) { ? /* ? ?源碼內(nèi)容 ? ?*/})( window );
上面這一小段代碼來(lái)自于1.9.0當(dāng)中jquery的源碼,它是一個(gè)無(wú)污染的JS插件的標(biāo)準(zhǔn)寫(xiě)法,專(zhuān)業(yè)名詞叫閉包。可以把它簡(jiǎn)單的看做是一個(gè)函數(shù),與普通函數(shù)不同的是,這個(gè)函數(shù)沒(méi)有名字,而且會(huì)立即執(zhí)行,就像下面這樣,會(huì)直接彈出字符串。
(function( window, undefined ) {
alert("Hello World!");
})( window );
可以看出來(lái)這樣寫(xiě)的直接效果,就相當(dāng)于我們直接彈出一個(gè)字符串。但是不同的是,我們將里面的變量變成了局域變量,這不僅可以提高運(yùn)行速度,更重要的是我們?cè)谝胘query的JS文件時(shí),不會(huì)因?yàn)閖query當(dāng)中的變量太多,而與其它的JS框架的變量命名產(chǎn)生沖突。對(duì)于這一點(diǎn),我們拿以下這一小段代碼來(lái)說(shuō)明。
var temp = "Hello World!";
(function( window, undefined ) { ? ? ? var temp = "ByeBye World!";
})( window );
alert(temp);
這段代碼的運(yùn)行結(jié)果是Hello而不是ByeBye,也就是說(shuō)閉包中的變量聲明沒(méi)有污染到外面的全局變量,倘若我們?nèi)サ糸]包,則最終的結(jié)果會(huì)是ByeBye,就像下面這樣。
var temp = "Hello World!";// ? ?(function( window, undefined ) {
var temp = "ByeBye World!";// ? ?})( window );
alert(temp);
由此就可以看出來(lái),jquery的外衣就是這一層閉包,它是很重要的一個(gè)內(nèi)容,是編寫(xiě)JS框架必須知道的知識(shí),它可以幫助我們隱藏我們的臨時(shí)變量,降低污染。
主要分三個(gè)部分,注冊(cè)Handler的Click事件
Click事件引發(fā)是開(kāi)始拖動(dòng),此時(shí)注冊(cè)Document的MouseMove事件,Move的時(shí)候修改對(duì)象的位置
松開(kāi)或者ESC的時(shí)候取消移動(dòng),注銷(xiāo)Document的Move事件
基本上所有的DragDrop都是這么實(shí)現(xiàn)的
jQuery選擇器的實(shí)現(xiàn)原理很簡(jiǎn)單,就是調(diào)用getElementsByName然后遍歷getAttribute,當(dāng)然還有g(shù)etElementsByTagName、getElementsById、querySelectorAll等等,jQuery一共有9種選擇器。
自己做的話,實(shí)現(xiàn)主要的選擇器,大致代碼也就一百多行吧。百度搜“實(shí)現(xiàn) jQuery 選擇器”有很多可以參考的代碼。
每次申明一個(gè)jQuery對(duì)象的時(shí)候,返回的是jQuery.prototype.init
對(duì)象,很多人就會(huì)不明白,init明明是jQuery.fn的方法啊,實(shí)際上這里不是方法,而是init的構(gòu)造函數(shù),因?yàn)閖s的prototype對(duì)象可
以實(shí)現(xiàn)繼承,加上js的對(duì)象只是引用不會(huì)是拷貝,new
jQuery,new
jQuery.fn和new
jQuery.fn.init的子對(duì)象是一樣的,只是有沒(méi)有執(zhí)行到init的不同,這里就不講原因了,等下一篇再講為什么會(huì)是這樣。
當(dāng)我們使用選擇器的時(shí)候$(selector,content),就會(huì)執(zhí)行
init(selectot,content),我們看看inti中是怎樣執(zhí)行的:
復(fù)制代碼
代碼如下:
if
(
typeof
selector
==
"string"
)
{
//正則匹配,看是不是HTML代碼或者是#id
var
match
=
quickExpr.exec(
selector
);
//沒(méi)有作為待查找的
DOM
元素集、文檔或
jQuery
對(duì)象。
//selector是#id的形式
if
(
match
(match[1]
||
!context)
)
{
//
HANDLE:
$(html)
-
$(array)
//HTML代碼,調(diào)用clean補(bǔ)全HTML代碼
if
(
match[1]
){
selector
=
jQuery.clean(
[
match[1]
],
context
);
}
//
是:
$("#id")
else
{
//判斷id的Dom是不是加載完成
var
elem
=
document.getElementById(
match[3]
);
if
(
elem
){
if
(
elem.id
!=
match[3]
)
return
jQuery().find(
selector
);
return
jQuery(
elem
);//執(zhí)行完畢return
}
selector
=
[];
}
//非id的形式.在context中或者是全文查找
}
else{
return
jQuery(
context
).find(
selector
);
}
}
這里就說(shuō)明只有選擇器寫(xiě)成$(‘#id')的時(shí)候最快,相當(dāng)于執(zhí)行了一次
getElementById,后邊的程序就不用再執(zhí)行了。當(dāng)然往往我們需要的選擇器并不是這么簡(jiǎn)單,比如我們需要id下的CSS為className,
有這樣的寫(xiě)法$(‘#id.className')和$(‘#id').find(‘.className');這兩種寫(xiě)法的執(zhí)行結(jié)果都是一樣的,比
如div
id=”id”span
class=”className”/span/div,返回的肯定都是span
class=”className”/span,但是執(zhí)行的效率是完全不一樣的。
在分析一下上邊的代碼,如果不是$(‘#id')這樣的簡(jiǎn)單選擇器的話,都會(huì)執(zhí)行find函
數(shù),那我們?cè)倏纯磃ind到底是做用的:
復(fù)制代碼
代碼如下:
find:
function(
selector
)
{
//在當(dāng)前的對(duì)象中查找
var
elems
=
jQuery.map(this,
function(elem){
return
jQuery.find(
selector,
elem
);
});
//下邊的代碼可以忽略,只是做一些處理
//這里應(yīng)用了js的正則對(duì)象的靜態(tài)方法test
//indexOf("..")需要了解一下xpath的語(yǔ)法,就是判斷selector中包含父節(jié)點(diǎn)的寫(xiě)法
//本意就是過(guò)濾數(shù)組的重復(fù)元素
return
this.pushStack(
/[^+]
[^+]/.test(
selector
)
||
selector.indexOf("..")
-1
?
jQuery.unique(
elems
)
:
elems
);
}
如果這樣寫(xiě)$(‘#id
.className'),就會(huì)執(zhí)行到擴(kuò)展的find(‘#id
.className',document),因?yàn)楫?dāng)前的this是document的jQuery數(shù)組,那我們?cè)诳纯磾U(kuò)展的find他的實(shí)現(xiàn),代碼比較
多,就不列出來(lái),總之就是從第二個(gè)參數(shù)傳遞進(jìn)行的dom第一個(gè)子節(jié)點(diǎn)開(kāi)始找,遇見(jiàn)#比對(duì)id,遇見(jiàn).比對(duì)ClassName,還有:+-等處理。
那我們要優(yōu)化,是不是就要想辦法讓第二個(gè)參數(shù)context的范圍最小,那樣遍歷是不是就很少了?
如果我們這樣寫(xiě)$(‘#id').find(‘.className'),那程序只這樣執(zhí)行
的,第一次init的時(shí)候執(zhí)行一步getElementById,就return了,接著執(zhí)行
find(‘.className',divDocument),divDocument就是我們第一次選擇的是div標(biāo)簽,如果document下有很
多dom對(duì)象的時(shí)候,這次只遍歷divDocument是不是少了很多次,而且在第一次選擇id的速度也要比遍歷快的多。
現(xiàn)在大家應(yīng)該是明白了吧。就是說(shuō)第一層選擇最好是ID,而是簡(jiǎn)單選擇器,目的就是定義范圍,
提高速度,這次就說(shuō)這些,選擇寫(xiě)法的優(yōu)化,其他的優(yōu)化,下次再說(shuō)。