剖析jQuery源碼

@description analyzing jquery.1.3.1.js
@author yanquan.xu(Henry)
@date 2013/5/11 19:19
@place campus

由於深愛着javascript語言,而對於業界的框架的層出不窮,我依然選擇了jquery。並非因爲其它框架不好,而是
自然而然的選擇和機緣的認識,所以一直用到現在,之後也會說它的不好。^.^,因爲沒有完美的東西。
使用那麼長得時間,直到前幾天才翻開它的源碼看了一下,感觸有一點,怕自己忘記,所以整理了一下,如果不好,
記得告訴我。^.^
我下載了jquery.1.3.1的版本進行閱讀,因爲所有版本的核心思想都是一樣的,後期更新到現在的1.9和即將出來的2.0
的核心都是一樣的,只是由於感覺新版本的功能增加得太多,代碼過於偏大不便閱讀,所以百度到了1.3版本的。
開始打開的源碼通常都有一些廢話在前面,就像下面一樣:
/*!
* jQuery JavaScript Library v1.3.2
* http://jquery.com/
* Download by http://www.codefans.net
* Copyright (c) 2009 John Resig
* Dual licensed under the MIT and GPL licenses.
* http://docs.jquery.com/License
*
* Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009)
* Revision: 6246
*/
其實不是廢話啦,這是每個公司或者個人的著作信息。這個不說了。
然後代碼就以這個開始了:(function(){
當你把內部全部代碼刪除掉,其實完整的寫法應該是:(function(){})();這個就是特別常見的閉包了,其實我第一次
聽到閉包還是會覺得生疏的,它的叫法意義類似於命名空間或者一個類一樣,這樣更親切。之所以在這裏面寫那麼多代碼,
就是不讓裏面的世界影響到了外面的世界,因爲你的總世界是一個web頁面,而不能因爲你寫的代碼影響到別人的代碼,變量
重寫了別人的,就是佔着別人的位置啦。
然後聲明瞭很多個變量,抽取了一些如下:
var 
// Will speed up references to window, and allows munging its name.
window = this,
// Will speed up references to undefined, and allows munging its name.
undefined,
// Map over jQuery in case of overwrite
_jQuery = window.jQuery,
// Map over the $ in case of overwrite
_$ = window.$,

jQuery = window.jQuery = window.$ = function( selector, context ) {
// The jQuery object is actually just the init constructor 'enhanced'
return new jQuery.fn.init( selector, context );
},
爲什麼這麼聲明,因爲js很隨和,一樣可以分開寫,也可以不強制寫var(你可以把var刪掉都沒關係,js很友好。)
其中覺得預先準備是做得很好的,比如將當前的執行環境對象即環境變量window存儲到內部變量window裏面,環境變量就是
this。this指向了window,因爲閉包的調用是window調用的,所以誰用了這個閉包,this就指着它。下面有個undefined,這
也許讓我們費解,其實只是基本功的問題,因爲沒有人會認爲undefined可以當做變量,只曾經模糊的記住undefined好像是
關鍵字,和null一樣類似,或者沒有搞清楚null和undefined區別。這裏沒有代表很多意思,只是說明了變量undefined的值是
undefined,好像很弱智很羅嗦啊。。。其實這是爲了別人重寫了undefined變量。第三變量的聲明把環境中得jQuery變量暫時
存儲到_jQuery變量,相當於打入冷宮,存在着閉包中,至於何時它能重見天日,就看你那時候用noConflict()函數把它解放
出來。同樣的道理,$是jQuery的姐妹一樣,形影不離,自然而然也要進入冷宮。之所以有如此做法,是下面的代碼需要這個
位置,所以不得不解決一下衝突。然後就是有點用的代碼的開始了,整個框架叫jQuery的聲明由此開始,它就是個函數,
參數是選擇符號和上下文,裏面的實現便是返回一個jQuery裏面的fn的init類的對象。
接下來就是一些累贅的正則表達式,如果有興趣可以看看它的正則的功力。如下:
// (both of which we optimize for)
quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,
// Is it a simple selector
isSimple = /^.[^:#\[\.,]*$/;
其實就是匹配選擇器的正則。
然後開始進入正文了,重心的代碼開始於:
jQuery.fn = jQuery.prototype = {
此句馬上進行了框架的初始化函數和原型的定義,比如css修飾函數,attr屬性函數,init初始化函數,其實init函數
也是大家所說的選擇器函數,被公認爲寫得最好的,我卻不這麼認爲,因爲我看完了所有代碼後,發現它只是思路清晰分類
的體現,只是冰山一角的體現。還有很多函數,比較多,就不累贅了,它們都是jQuery對象的函數,作用於對象上面,這個
非常重要。只是大家會覺得很奇怪,爲什麼原型的方法會作用於原型的內部類的對象。慢慢看完原型的實現後,我們又看到
了這一句:jQuery.fn.init.prototype = jQuery.fn;我至始至終覺得就是這一句就是這個框架的亮點,它讓我豁然開朗和
晴天霹靂的感覺,它把初始化函數們又回掛到了初始化函數內部類的原型,很繞口,沒辦法,重點就是這裏。我簡寫一下,
或許更便於理解:
jQuery.fn = jQuery.prototype = {
init:function(){}
};
jQuery.fn.init.prototype = jQuery.fn;
至此已經很簡便了,只能意會,如果看不懂,我也沒辦法。它的優點在於擴大了原生js操作dom元素的能力,你可以看到
選擇器函數init裏面有一句:var elem = document.getElementById( match[3] );然後返回了這個元素。當我們可以用擴展的
原型函數的時候,就會發現css(key,value)比你寫elem.style.key = value;要好用得多。
往下看,又會看到非常核心的函數出場了,就是集成函數的實現:
jQuery.extend = jQuery.fn.extend = function() {
很明顯,它又掛到原型函數裏面去了,但是也留給了jQuery對象裏面了,如果說成是jQuery類的靜態方法,你可能更能
理解,是的,之後會看到它的強大作用。它的實現不亞於選擇器函數,實現了深層集成和淺層的集成,實現不累贅講述,因爲
每一個重要的函數代碼,jQuery都寫到一起,很長,不喜歡這樣的風格。不過反正也沒人看,無所謂。
然後我們在extend下面可以看見,因爲作者又集成了很多函數,太長了,不說明了,只是應該注意的是,這些函數不僅僅
集成到了jQuery.fn裏面,而且jQuery裏面也會有得。就是說對象方法當然有,但是也是jQuery靜態方法,因爲下面代碼實現
會用到這些函數。
接下來就是瀏覽器的判斷,就是正則表達式的測試:
jQuery.browser = {。。。
接下來我們可以看到作者將函數進行了細化擴展,比如我們的所有節點查找的函數都是經過剛集成的函數得以實現的。並且
在fn裏面擴展了這些細化,使得我們可以隨心所欲的查找到我們需要的節點,比如siblings(),next(),prevAll(),children()等等
然後又用each函數擴展了許許多多的函數,不一一列舉了,好煩啊。總之有兩種擴展啦,就是它了each和extend,但是擴展
的對象是又區別的。然後它羅嗦的寫了那麼多函數之後,引用了點別人的東西,這個東西可大了:
/*!
* Sizzle CSS Selector Engine - v0.9.3
* Copyright 2009, The Dojo Foundation
* Released under the MIT, BSD, and GPL Licenses.
* More information: http://sizzlejs.com/
*/
這個就很厲害了,就是著名的Sizzle,這個是css選擇器的引擎,它是強大的選擇器的實現。jQuery依靠它,完成了其餘工作
的實現。總之,又是一陣羅嗦之後,我們翻到了下面,驚訝的發現它又是集成又是集成又是集成,然後代碼就這麼集成完了,
至此,你終於知道這個extend是多麼強大和重要。
說千道萬,不如自己去看一下。不過感覺jQuery包裝是很好的,讓我們覺得很精美,但是裏面卻是“無比醜陋”,因爲它
的目標只有一個,就是寫得少,實現多。正因這個原因,所以讓它的代碼是非常濃縮的精華寫法,不按照平常我們的語法類似,
而是怎麼高效,怎麼簡潔,怎麼方便怎麼寫。反正我們都只用它,不會看它的。雖然是如此,不會影響它在我心中的地位。
裏面的實現實在很有欣賞的妙處,比如擴展的寫法,瀏覽器ie的return id的bug,高效快速的引用,正則表達式的高效
利用。

-----------------------------------------------------------------------------------------JavaScript羣:55732875

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章