jQuery 原始碼解讀 (I)

這次想要開啟一個 jQuery 原始碼解讀的文章系列,原因是因為原本以為我已經算是了解 JavaScript 了,但最近遭受打擊,於是想要再重新學習 JavaScript,我想最好的方法就是看懂大師的 code。 jQuery 應該也算是公認的大師作品了。所以就選定 jQuery 來研讀好了 🙂

如果你也曾經自認為懂 JavaScript,建議您看看你其實並不懂JavaScript,評量看看您是否真的了解,通常看過之後大部分人會覺得自己知道,但我必須說除非你確認你有開發並應用到相關的知識,不然只是從書上看過並不代表你真的了解!尤其 JavaScript 還有很多出乎正常邏輯外的運算結果!一起來精進 JavaScript 吧。

這次就讓我們先從 jQuery 的進入點來看吧:

jQuery 的進入是透過 self executing anonymous function (or self invoking anonymous function) 的 pattern。

function(window, undefined){}

這定義了一個 Anonymous function

之後透過括號 () 包住 Anonymous function: (function(window, undefined){}) 取得 evaluate 過的 Anonymous function 再透過 () 去執行 Anonymous function

(function(window, undefined){})();

這邊有個重點是一定要先用 () 包住 Anonymous function ,否則會得到 syntax error。 Paul Irish 的 10 things I learned from jQuery 影片裡面關於這一點似乎說錯,他說技術上這一點是 optional ,但很明顯的不是如此。

不過另外他提到的 Facebook 的 source code 裡面有看到一些相同作用但不同語法的方式是:

!function(window, undefined){}();   或    +function(window, undefined){}();

這部份就是正確的,基本上都只是需要讓 Anonymous 先產生定義,再透過後面的 () 執行它。

到目前為止僅是語法的部分,但在這之外 jQuery 使用這 self invoking anonymous function 的 pattern 一定有其意義。最重要的意義我想應該就在於 John Resig 自己的書 Secrets of the JavaScript Ninja 裡面所提到的 Library Wrapping。透過 Anonymous function 的 local scope 將 library 本身定義的 variables 以及 functions 限制在 local scope 裡面,這麼一來不會影響全域的命名空間,同時也避免 jQuery 自己的變數以及其他定義被外界影響。

了解語意之後,再來看看 jQuery Anonymous function 的參數 window 以及 undefined 的意義。第一個參數 window 很容易理解,在呼叫 Anonymous function 的時候傳入 window,因此而將 window 從 global 變數轉換成在 local scope 的一個 reference。雖然說不傳也可以直接存取 window 這個變數,但這邊轉換成 local scope 的 window reference 之後可以提升一些效能。原理大概是在 JavaScript 裡面存取變數的時候會先在 local scope 找, 找不到的話再往上找 global scope。這邊的作法就會讓 window 的存取少了一層,因此可以增進效能。不過那也是因為 jQuery 會大量用到 window,如果你的 code 裡面沒有大量用到應該也是不用這樣做 🙂

至於 undefined 這個參數,首先第一個特別的點是在呼叫的時候沒有傳第二個參數,所以透過 JavaScript 的語法讓第二個參數 “underfined” 帶入 window.undefined。這樣做的原因我聽過兩個,第一個是說由於 undefined 是一個 global 變數,有可能被改掉,所以必須透過這個方式綁定 undefined 的值。這樣一來就不怕 undefined 的值被突然改掉了。第二個說法是,有些瀏覽器的 undefined 不叫 undefined,所以透過這個方法可以強制讓 undefined 都是 undefined。基本上兩個方法都合理,但我也都有點存疑。第一個說法讓我存疑的是在於那為什麼就不管其他的 global variables?而只處理 undefined?也許是因為 jQuery 真的只用到 undefined 吧。再來是,我實驗了把 window.undefined 的值改掉,結果發現改不掉,看來現在瀏覽器(筆者使用 Chrome 19.0.1084.56 測試)很聰明的會保護一些特別的值。所以目前就我看起來真不是理由 XD 第二個說法存疑的點是真的有瀏覽器沒有支援 window.undefined ? 也許真的有,但至少我還沒遇過。

好的, jQuery 原始碼解讀第一趴就先到這裡了。 待續…

參考:
jQuery, John Resig
10 things I learned from jQuery source, Paul Irish
Speed up your JavaScript, Nicholas C. Zakas
Secrets of the JavaScript Ninja, Jogn Resig



Comments
  1. 回覆

Leave a Reply

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