jQuery 原始碼解讀 (II)

上次筆者在 jQuery 原始碼解讀 (I) 分享了關於 jQuery 進入點的見解,如果以 jQuery 原始碼結構來說的話上一次的討論在於分析了 jQuery 的 intro 以及  outro。在進入點之後,我們就可以來進入 jQuery 的核心:core.js 部分了。

由於 core 本身帶著非常多的碼,筆者想針對幾個比較重要的點來解讀,所以我們先把它簡化成這樣:

從上面的 code 來看,我們一般在使用 jQuery 時,最常用的是 $(“selector”),而 $ 其實就等於 window.jQuery (core 這邊其實有一段 code 在處理 window.jQuery / window.$ 可能會有 naming conflict 的問題,我們這次先跳過)。 所以 $ 實際上會是執行

newjQuery.fn.init(selector,context);

這邊呢,jQuery.fn.init 是 jQuery.prototype 中的一個 function,而由於這個敘述:

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

使得 jQuery.fn.init 也成為 jQuery 的 constructor。這樣一來的話,基於 prototype 繼承的特性,就可以透過在 jQuery.fn 上動態新增 function 來達到擴充的功能。也就是說由於 JS 的物件都會有一個 reference 指向 prototype object,因此在後面新增到 prototype 的 function 也會讓已經生成的 object 具有該新 function。

而以 jQuery 為基礎來開發的人一定很清楚 jQuery 的可串接性 (chaining) 的寫法。比如說這一段 code:

其實可以寫成:

之所以可以這樣寫是因為幾乎每一個 jQuery function 都會 return this; // i.e. jQuery object。當然會有例外,比如 .val() 就不行。 也就是說當要擴充 jQuery.fn 的時候也必須要把 chainability 考慮進去。

再來有一點,我覺得很少人討論,我之前在用 jQuery 的時候,每次下 selector,jQuery 都會回傳一個 array,在 inspector 裡面都會看到 jQuery.fn.jQuery.init[n] ,每次我都覺得很奇怪,但是稍微看一下 code 又看不出為什麼。後來我很認真地研究終於發現原來只要一個 object 裡面有 length 這個屬性,同時又有 splice 這個 function 那行為就會看起來很像 array 但是並不是真的 array instance。

很容易驗證,在 console 裡面這樣打就可以看得出來了:

var fakearray = {
length: 0,
splice: function(){}
};
undefined
fakearray
[]
fakearray.splice = null;
null
fakearray
Object


不知道是不是筆者太嫩,我看網路上在討論 jQuery source 都沒有講到這個,可能大家都知道,只有我不知道 XD

好的, jQuery 原始碼解讀第二趴就先到這裡了。 待續…
jQuery 系列文章:


Comments
  1. Joe
    回覆
  2. kswlee
    回覆

Leave a Reply

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *