jQuery的無new創(chuàng)建方法

一般我們去寫一個框架,會采用什么樣的設計呢神帅?比如設計一個jQuery框架律罢,一般我們會創(chuàng)建一個函數(shù)對象

functionjQuery(params){  //構造函數(shù)}

jQuery.prototype.init = function(params){

//初始化操作

}jQuery.prototype.html=function(html){

//實現(xiàn)類似設置innerHTML的操作

}varjq =newjQuery("#id");

jq.init();

jq.html("test");

我想這是我們最常見的使用方式缓待,這種方式需要new一個新的實例婚陪,然后再進行初始化操作族沃,然后才能繼續(xù)操作,很顯然這樣會比較繁瑣而且代碼較多,而jQuery中的使用方法卻非常簡潔:

獲取指定元素:$("#id")/$(".class")/$("body").html("test");

創(chuàng)建html片段$("

").html("test");

設置文檔加載完成后的方法$(function(){XXX});

等等泌参,為何jQuery的使用方法如此簡單脆淹,這是因為jQuery設計的是一種無new的創(chuàng)建方法,這是jQuery獨特的設計思路之一沽一。

我們打開jQuery初始化的這塊代碼盖溺,發(fā)現(xiàn)基本結構是這樣子的(提取主要框架部分源碼):

(function( window, undefined ) {varjQuery =function( selector, context ) {returnnewjQuery.fn.init( selector, context, rootjQuery );

};

jQuery.fn= jQuery.prototype ={

constructor: jQuery,

init:function( selector, context, rootjQuery ) {

if ( !selector ) {

return this;

}

if ( typeof selector === "string" ) {

if ( match && (match[1] || !context) ) {

return this;

} else if ( !context || context.jquery ) {

return ( context || rootjQuery ).find( selector );

} else {

return this.constructor( context ).find( selector );

}

} else if ( selector.nodeType ) {

return this;

} else if ( jQuery.isFunction( selector ) ) {

return rootjQuery.ready( selector );

}

if ( selector.selector !== undefined ) {

this.selector = selector.selector;

this.context = selector.context;

}

return jQuery.makeArray( selector, this );

},

html:function(value){

//實現(xiàn)類似innerHTML操作

}? ? }? ? jQuery.fn.init.prototype= jQuery.fn;

})( window );

1. 首先把代碼封裝在一個匿名函數(shù)里面,防止污染全局環(huán)境铣缠,然后創(chuàng)建一個對象jQuery烘嘱,這個對象接受兩個參數(shù)selector,context,其中selector就是我們通常傳入的 #id,.class等字符串,這個對象函數(shù)里面并沒有做什么邏輯而是直接返回了一個原型上的init方法,然后把參數(shù)傳了進去蝗蛙。

2. init方法接受了3個參數(shù)蝇庭,然后在內部進行了各種判斷,根據不同的場景歼郭,返回一個不同的實例對象,類似一個工廠方法辐棒。

3. 將jQuery.fn.init的原型掛載到jquery的原型上病曾。

4. 將jQuery的constructor還原為jQuery

init方法的內部邏輯我們后面再看,首先看下為何jQuery要這樣做漾根?

首先jQuery在構造函數(shù)里面就執(zhí)行了new方法并執(zhí)行了init方法泰涂,將new和init兩步直接合并成一步,而且自帶new操作辐怕,不需要用戶再去進行new的操作逼蒙,但是為何要使用一個原型上的init方法,而不是在自身自己new出一個對象呢寄疏?

想象一下如果jQuery這樣寫

varjQuery =function( selector, context ) {

//做上面的各種場景判斷returnnewjQuery( selector, context, rootjQuery );

}

這樣寫會存在一個問題是牢,jQuery函數(shù)內部new一個新的jQuery,然后會一直這樣new下去無限循環(huán)陕截,陷入死循環(huán)驳棱。為了防止這種情況的出行,jQuery將這部分邏輯放在了原型中的一個init方法农曲,由init方法來進行工廠方法的處理社搅,return new?jQuery.fn.init( selector, context, rootjQuery ),這樣就避免了死循環(huán)的問題,而且實現(xiàn)了一步到位的初始化形葬。

但是這樣寫還存在一個問題合呐,init方法里面的return this是指向的jQuery的實例對象,那他將無法訪問jQuery的原型對象笙以,比如說jQuery.prototype.html方法淌实,因為html的方法是jQuery.prototype上的所以init方法無法訪問這個函數(shù),為了解決這個問題源织,我們看到之前的源碼有最后一行:

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

其中jQuery.fn就是jQuery.prototpye翩伪,也就等價于

jQuery.prototpye.init.prototype = jQuery.prototpye;

這句話的意思是,把init的方法的原型改為指向jQuery的原型谈息,這樣new init的出來的實例對象也就等價于new jQuery的實例對象缘屹,所以也就可以訪問jQuery的原型方法了。

jQuery.prototype.init和jQuery的原型指向的是同一個對象侠仇,這樣不管是init還是jQuery去修改原型對象都是等價的轻姿,這樣就實現(xiàn)了上面提到的問題。

最后逻炊,jQuery再把constructor還愿回來到jQuery互亮,防止構造函數(shù)指向錯誤,引起調用問題余素,為何要這樣處理呢豹休?因為我們是把jQuery的prototype直接覆蓋成了一個新的實例對象,所以jQuerty的constructor就變成了{}的構造函數(shù)Object,所以需要將constructor還原為真正的jQuery桨吊。

對比下兩種原型改寫方式:

//方式1

jQuery.prototype.html =function(value){}

//方式2jQuery.prototype={

html:function(value){}

}

兩種方式看起來好像沒啥區(qū)別威根,但其實區(qū)別很大,第一種是給jQuery的prototype新增一個方法视乐,這種方式是不會影響jQuery的constructor洛搀,還是function jQuery(),

而第二種方式是直接覆蓋了jQuery的prototype,這種情況下的constructor會被直接改寫為{html:function(value)}這個實例對象的構造函數(shù)佑淀,也就是function Object()

所以需要重置一下jQuery的constructor

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末留美,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子伸刃,更是在濱河造成了極大的恐慌谎砾,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件捧颅,死亡現(xiàn)場離奇詭異棺榔,居然都是意外死亡,警方通過查閱死者的電腦和手機隘道,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進店門症歇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來郎笆,“玉大人,你說我怎么就攤上這事忘晤⊥痱荆” “怎么了?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵设塔,是天一觀的道長凄吏。 經常有香客問我,道長闰蛔,這世上最難降的妖魔是什么痕钢? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮序六,結果婚禮上任连,老公的妹妹穿的比我還像新娘。我一直安慰自己例诀,他們只是感情好随抠,可當我...
    茶點故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著繁涂,像睡著了一般拱她。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上扔罪,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天秉沼,我揣著相機與錄音,去河邊找鬼矿酵。 笑死唬复,一個胖子當著我的面吹牛,可吹牛的內容都是我干的坏瘩。 我是一名探鬼主播盅抚,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼漠魏,長吁一口氣:“原來是場噩夢啊……” “哼倔矾!你這毒婦竟也來了?” 一聲冷哼從身側響起柱锹,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤哪自,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后禁熏,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體壤巷,經...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年瞧毙,在試婚紗的時候發(fā)現(xiàn)自己被綠了胧华。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片寄症。...
    茶點故事閱讀 38,569評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖矩动,靈堂內的尸體忽然破棺而出有巧,到底是詐尸還是另有隱情,我是刑警寧澤悲没,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布篮迎,位于F島的核電站,受9級特大地震影響示姿,放射性物質發(fā)生泄漏甜橱。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一栈戳、第九天 我趴在偏房一處隱蔽的房頂上張望岂傲。 院中可真熱鬧,春花似錦荧琼、人聲如沸譬胎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽堰乔。三九已至,卻和暖如春脐恩,著一層夾襖步出監(jiān)牢的瞬間镐侯,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工驶冒, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留苟翻,地道東北人。 一個月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓骗污,卻偏偏與公主長得像崇猫,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子需忿,可洞房花燭夜當晚...
    茶點故事閱讀 43,446評論 2 348

推薦閱讀更多精彩內容