每次申明一個(gè)jQuery對(duì)象的時(shí)候,返回的是jQuery.prototype.init
成都創(chuàng)新互聯(lián)公司專(zhuān)注于企業(yè)全網(wǎng)營(yíng)銷(xiāo)推廣、網(wǎng)站重做改版、青海網(wǎng)站定制設(shè)計(jì)、自適應(yīng)品牌網(wǎng)站建設(shè)、H5網(wǎng)站設(shè)計(jì)、商城網(wǎng)站開(kāi)發(fā)、集團(tuán)公司官網(wǎng)建設(shè)、成都外貿(mào)網(wǎng)站制作、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁(yè)設(shè)計(jì)等建站業(yè)務(wù),價(jià)格優(yōu)惠性價(jià)比高,為青海等各大城市提供網(wǎng)站開(kāi)發(fā)制作服務(wù)。
對(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ō)。
$ 是 JQuery 常用的一個(gè)回傳函數(shù),定義為 "選取" 英文是 selector 的縮寫(xiě)
例子︰
$.function();
就是 選取 JQuery 定義的 function() 執(zhí)行
$('input')
就是 選取 HTML 當(dāng)中全部的 input 標(biāo)簽
$('#abc')
就是 選取 HTML 當(dāng)中 ID 名稱(chēng)為 abc 的物件
$.fn.testing = function() {}
就是 選取 JQuery 內(nèi)核函數(shù) fn (函數(shù)) 回傳給 testing 這個(gè)名稱(chēng)、定義為一個(gè)功能 function()
jquery是javascript的一個(gè)類(lèi)庫(kù),說(shuō)到底jquery就是javascript jquery主要是用來(lái)簡(jiǎn)化javascript的各種操作以及解決各種瀏覽器之間的兼容性 用jquery能辦到的用javascript都能辦到。
jquery是javascript的一個(gè)插件,所以說(shuō)jquery的原理就是封裝javascript;
方法添加可以參考一些jquery插件,例如:resizableColumns,實(shí)現(xiàn)方法類(lèi)似下面:
$.fn.Plugname = function(options) {
}
這段時(shí)間在學(xué)習(xí)研究jQuery源碼,受益于jQuery日益發(fā)展強(qiáng)大,研究jQuery的大牛越來(lái)越多,學(xué)習(xí)的資料也比前兩年好找了,有很多非常不錯(cuò)的資源,如高云的jQuery1.6.1源碼分析系列。這些教程非常細(xì)致的分析了jQuery內(nèi)部原理和實(shí)現(xiàn)方式,對(duì)學(xué)習(xí)和理解jQuery有非常大的幫助。但是個(gè)人認(rèn)為很多教程對(duì)jQuery的整體結(jié)果把握不足,本人試圖從整體來(lái)闡述一下jQuery的內(nèi)部實(shí)現(xiàn)。
大家知道,調(diào)用jQuery有兩種方式,一種是高級(jí)的實(shí)現(xiàn),通過(guò)傳遞一個(gè)參數(shù)實(shí)現(xiàn)DOM選擇,如通過(guò)$(“h1″)選擇所有的h1元素,第二種是較為低級(jí)的實(shí)現(xiàn),如果通過(guò)$.ajax實(shí)現(xiàn)ajax的操作。那么,這兩種方式到底有何不同?用typeof函數(shù)檢測(cè)$(‘h1′)和$.ajax,類(lèi)型分別為object和function,稍微學(xué)過(guò)jQuery的都知道或者聽(tīng)過(guò)過(guò),前者返回的是一個(gè)jQuery對(duì)象,那么jQuery對(duì)象是什么,它和jQuery是什么關(guān)系呢?我們先來(lái)通過(guò)for(var
i
in
$(”))
document.write(i+”
:::”+$(“”)[i]+””);打印一下jQuery對(duì)象的屬性和對(duì)應(yīng)的值,可以看到它有100多個(gè)屬性,通過(guò)console輸入$(“*”)可以看到大部分屬性是繼承自jQuery原型的屬性,jQuery對(duì)象實(shí)際上是這樣一個(gè)對(duì)象:
所以我們來(lái)推測(cè),jQuery的實(shí)現(xiàn)可能是類(lèi)似這樣的:
function
jQuery(){
this[0]="Some
DOM
Element";
this[1]="Some
DOM
Element";
this[2]="Some
DOM
Element";
this.length=3;
this.prevObject="Some
Object";
this.context="Some
Object";
this.selector="Some
selector";
}
jQuery.prototype={
get:function(){},
each:function(){},
......
}
這些代碼通過(guò)new操作符就就能創(chuàng)建出擁有上述屬性的jQuery對(duì)象,但是實(shí)際上我們調(diào)用jQuery創(chuàng)建jQuery對(duì)象時(shí)并沒(méi)有使用new操作符,這是如何實(shí)現(xiàn)的呢?來(lái)看jQuery的實(shí)現(xiàn):
var
jQuery
=
function(
selector,
context
)
{
//
The
jQuery
object
is
actually
just
the
init
constructor
'enhanced'
return
new
jQuery.fn.init(
selector,
context,
rootjQuery
);
}
jQuery.fn=jQuery.prototype={
jquery:
core_version,
init:function(selector,context){
//some
code
return
this;
}
//some
code
there
//......
}
jQuery.fn.init.prototype=jQuery.fn;
這里有幾點(diǎn)做得非常巧妙的地方,第一點(diǎn)是通過(guò)jQuery原型屬性的init方法來(lái)創(chuàng)建對(duì)象來(lái)達(dá)到不用new創(chuàng)建對(duì)象的目的,第二點(diǎn)是對(duì)init方法內(nèi)this指向的處理。我們知道,通過(guò)調(diào)用init返回一個(gè)jQuery的實(shí)例,那么這個(gè)實(shí)例就必須要繼承jQuery.prototype的屬性,那么init里面這個(gè)this,
就繼承jQuery.prototype的屬性。但是init里面的this,受制于作用域的限制,并不能訪問(wèn)jQuery.prototype其它的屬性,jQuery通過(guò)一句'jQuery.fn.init.prototype=jQuery.fn'把它的原型指向jQuery.fn,這樣以來(lái),init產(chǎn)生的jQuery對(duì)象就擁有了jQuery.fn的屬性。
到這里,一個(gè)jQuery的基本原型就浮出水面了。這里有兩個(gè)對(duì)象,一個(gè)是jQuery這個(gè)構(gòu)造函數(shù),另外一個(gè)是這個(gè)構(gòu)造函數(shù)產(chǎn)生的對(duì)象(我們稱(chēng)之為jQuery對(duì)象,它和普通對(duì)象沒(méi)有什么區(qū)別),
如下關(guān)系圖:
可以看到j(luò)Query構(gòu)造函數(shù)和jQuery.prototype均有各自的屬性和方法,兩者的調(diào)用方法各不一樣,這兩個(gè)對(duì)象都有一個(gè)extend方法,都是用來(lái)擴(kuò)展自身的屬性和方法,在jQuery內(nèi)部,extend的實(shí)現(xiàn)實(shí)際是靠一樣的代碼,
將在后面的源碼分析中做以詳細(xì)的分析。
var $=function(a){
var UNDEFINED;
if(a!=UNDEFINED!=null){
//調(diào)用有參方法
}else{
//調(diào)用無(wú)參方法
}
}
你這個(gè)好像不是這么這么說(shuō)的
$ 這是一個(gè)對(duì)象
$("選擇器")得到的是對(duì)象的實(shí)例
$.function是在對(duì)象上的方法,不是對(duì)象實(shí)例的方法,這兩個(gè)是不一樣的