從github直接拷貝過來,排版不是很友好,可點擊這里查看github上的文章
前端的童鞋對jQuery絕對不會陌生,有不少剛入門的筒子,在不知JS為何物的時候,就已經在用jQuery了。這也應該歸功於前端惡劣的生存環境:各自為政的瀏覽器廠商,依舊嚴峻的兼容性問題,並不好用的原生API。。。
使用jQuery的理由有很多,喜歡它的理由也很多,優雅的接口,豐富的插件,完善的文檔等。作為一名有進取心的前端攻城獅,大家心理或多或少都有一個框架夢,總用它人寫的庫,內心總歸有些那么不是滋味。
那好吧,干脆自己寫一個,“師夷長技以自強”嘛,於是熱火朝天地開工,一個又一個小JQ就這樣橫空出世。再精心挑選上好的測試用例證明自己的庫比其他庫更牛逼,當然,jQuery基本都在對比之列。
此處省略三千字。。下面開始進入jQuery源碼分析之路
jQuery是什么
好吧,這里的jQuery指的並不是“jQuery庫”,而是jQuery這個對象。首先用你習慣使用的編輯器打開jQuery-1.9.1.js,最好能夠支持代碼高亮和智能折疊。好家伙,源碼加注釋共9500++行,怪嚇人的。沒錯,這是每個有志學習jQuery源碼的童鞋需要過的第一道坎。其實,完全沒有必要害怕,將多余的噪音去掉,其實jQuery就是下面幾行代碼而已:
(function( window, undefined ) { var jQuery = function( selector, context ) { // The jQuery object is actually just the init constructor 'enhanced' return new jQuery.fn.init( selector, context, rootjQuery ); }; window.jQuery = window.$ = jQuery; })( window );
我們更為常用的美元符號$,其實就是jQuery的同名對象,而jQuery是個方法,它的作用是返回一個jQuery對象,更確切地來說,是jQuery.fn.init對象。至於為什么會返回jQuery.fn.init對象,可以小小參考下之前寫的另一篇文章【jquery學習筆記】美元背后的一點小技巧
從一行代碼說jQuery的核心源碼結構
有下面這么一行代碼
$('#casper').addClass('handsome‘),
這行代碼的作用不用多說:給ID為casper的dom節點添加一個名為handsome的class。很簡單的一句代碼,拆成兩部分來看:
$('#casper')返回一個jQuery對象,該對象的屬性’0‘包含了選中的dom節點=> $('#casper')[0] === document.getElementById('casper').addClass('handsome')給選中的dom節點添加handsome類,addClass為jQuery的prototype方法
於是我們把之前的那個簡陋的骨架再豐滿下,整個jQuery的骨架就基本出來了,里面的代碼關鍵點在**源碼骨架**后面會逐個進行講解
源碼骨架
(function( window, undefined ) { 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 = { constructor: jQuery, init: function( selector, context, rootjQuery ) { //... }, ... }; jQuery.fn.init.prototype = jQuery.fn; //extend方法,用來擴展jQuery,或jQuery.fn jQuery.extend = jQuery.fn.extend = function() { //... }; jQuery.fn.extend({ addClass: function( value ) { //... return this; //返回this,鏈式調用的秘密 } }); window.jQuery = window.$ = jQuery; })( window );
return new jQuery.fn.init( selector, context, rootjQuery );
$('#casper')跟new $('#casper')是一樣的。個人覺得這里設計的原因,一個減少寫一堆new的麻煩,同時也可以避免開發者不小心遺漏了new導致的詭異bug。當然,不好的地方是,代碼有點繞,這也算是jQuery源碼的其中一個特點。
jQuery.fn = jQuery.prototype
沒什么好講,jQuery.prototype為jQuery的原型方法,這里用jQuery.fn來代替jQuery.prototype,只是為了少寫幾個字符,平常寫插件時就是在這東東上面做修改
jQuery.fn.init.prototype = jQuery.fn
很好很繞的一個語句,上面說了$(’#casper‘)返回的其實是個jQuery.fn.init對象。所以,這里的作用,是讓jQuery.fn上的方法都成為jQuery.fn.init對象的原型方法。 這個語句應該讓很多剛接觸jQuery源碼的人感到困惑,包括我(=_=),可以試jQuery.fn.init.prototype.init.prototype.init...,如果你願意可以一直寫下去。
addClass: function( value ) {...
下面這段代碼很短很關鍵,別看它很簡單,jQuery眾多強大的接口就是這樣通過jQuery.fn.extend一個一個擴展出來的,不贅述
jQuery.fn.extend({ addClass: function( value ) {
寫在后面
本文對jQuery源碼核心結構進行了粗略的介紹,當然jQuery實際的源碼要比這個復雜得多,但只要掌握了上面的要點,后續的分析就會輕松很多。jQuery源碼之所以比較難看懂,是因為里面有許多為了解決糟糕的瀏覽器兼容性問題而引進的hack。
萬事開頭難,這是筆者jQuery源碼解析的開篇之作,網絡上這類的文章很多,而且有些寫的很不錯,這里寫作的原因,一來總結,二來備忘。
未完待續。
