問答形式閱讀jQuery源碼(一)

來源:互聯網
上載者:User

標籤:

筆者閱讀了園友艾倫 Aaron的系列部落格《jQuery源碼分析系列》,主要是閱讀的jQuery的原理,然後跑園友的代碼,真正對jQuery源碼的閱讀並不多。主要是直接閱讀jQuery源碼,一次能讀懂的部分並不多,不如先閱讀源碼解析的文章,然後再閱讀收穫更大。筆者在閱讀完園友艾倫的全部jQuery源碼部落格之後,準備真正開始閱讀jQuery的原始碼。而閱讀的形式屬於自問自答,把在閱讀部落格時候的留下來的疑問提出來,再通過自己閱讀源碼的形式對其解答;當然也包括在閱讀原始碼的時候那些讀不懂的地方,提出疑問,然後在慢慢消化解答。

這個jQuery源碼系列並非教程,而是筆者的學習jQuery源碼的筆記,因此才會採取問答這種不系統的形式。如果大家想系統學習jQuery源碼,還是請仔細閱讀艾倫 Aaron的部落格;或是直接閱讀jQuery在gitbub上的源碼(目前的master版本是version to 3.1.1-pre.,筆者閱讀的也是這個版本的代碼)。如果在閱讀後也和筆者一樣,對一些內容存在疑問,可以看看筆者的系列部落格,看看你有沒有你疑惑的問題。

 

提問:如何構建jQuery的源碼

在我開始閱讀jQuery的源碼時,發現原始碼本身是有模組化的,而艾倫 Aaron閱讀的版本沒有,他是直接閱讀的dist後的代碼。那麼jQuery是如何構建原始碼的呢?

答:閱讀jQuery在github上的README.md檔案,裡面已經說得非常清楚了。先安裝git用戶端和nodejs及npm。然後將github上的資源複製到本地,找一個目錄,然後開啟命令列,輸入git的clone命令:

git clone git://github.com/jquery/jquery.git

本地就會複製出jQuery的原始碼:

然後進入該目錄下,在命令列上運行如下命令,jQuery就會自動安裝npm模組,並構建jQuery了。

npm run build

最後在dist目錄中,會構建出我們想要的jQuery檔案了。

 

提問:git上的jQuery目錄結構是怎樣的

答:具體目錄結構可以看,這裡逐個介紹一下各個目錄和檔案的作用:

.github git相關目錄
build 構建相關的指令檔,筆者大概閱讀了一下,主要是建立兩個Grunt任務,負責構建(bulid)和輸出(dist)
dist 輸出構建後的檔案,主要是jquery.js和jquery.min.js,以及jquery.min.map。這些就是我們最終使用的js檔案了
external 放依賴的第三方代碼,jQuery中最重的第三方庫sizzle就在這裡
node_modules nodejs的模組檔案,構建時候安裝的node非全域模組都放在這裡,屬性nodejs的小夥伴應該很清楚了
src jQuery自身的原始碼的目錄,這就是我們主要閱讀的部分
test 單元測試用例
.babelrc Babel的設定檔
.editorconfig editorconfig的設定檔,editorconfig是協助開發人員在不同的編輯器和IDE之間定義和維護一致的代碼風格的配置,很多ide都支援editorconfig的外掛程式,使用這個就可以使各種ide下都能自動將代碼顯示成editorconfig約定的格式
.eslintignore eslint相關檔案,配置不用於eslint文法檢測的檔案目錄
.eslintrc.json eslint的設定檔。eslint和jshint比較像,可以認為是jshint的升級版,都是用來做文法檢測的。
.gitattributes git相關檔案,用於設定檔案的對比方式
.gitignore git的設定檔,配置用於配置不需要加入版本管理的檔案
.mailmap 貌似是一個郵件地址清單
.npmignore npm相關檔案,配置哪些檔案不需要被發布到npmjs.org
.npmrc npm的設定檔
.travis.yml Tarvis-CI的設定檔,持續整合用的,github整合了持續整合服務travis,每一次push之後,travis就會定時執行“npm test”來測試專案
AUTHORS.txt 貢獻者名錄
CONTRIBUTING.md 貢獻代碼指引
Gruntfile.js Grunt的設定檔
LICENSE.txt 授權協議
README.md github項目的說明文檔
package.json npm的包檔案

幾個地方值得注意一下:

1.jQuery是用RequireJs做模組化工具的,所以jQuery的原始碼是用AMD規範。AMD這個模組化規範主要活躍於基於瀏覽器的js模組管理,他有著非同步載入、依賴前置等非常好的特性,當然用來做後端的代碼模組管理也可以,但是筆者終究認為這裡用AMD有點“大材小用”了。jQuery用AMD規範做模組化管理,可能是曆史原因的影響,早些年模組化工具不像如今這麼成熟。

2.jQuery是用Grunt構建的,jQuery自己做了構建的Grunt任務,具體代碼可以參考build目錄下的Grunt任務和Grunt的設定檔Gruntfile.js。基於Grunt,jQuery完成測試、構建、合并代碼、壓縮等工作,最終把構建好的檔案拷貝到dist目錄裡面。

3.jQuery配置了npm包相關的配置,說明jQuery本身也被發布到了npmjs.org上,我們可以直接用npm安裝jQuery。

4.jQuery有Babel的設定檔,那原始碼是不是用ES6的文法呢?

 

提問:jQuery有Babel的設定檔,難道jQuery的原始碼使用了ES6的文法?

答:答案是沒有的,我們先不看Babel在Grunt裡面的配置,直接試一下能不能在原始碼中使用ES6。

先將原始碼裡面添加一條ES6的文法,然後執行構建。這時我們會發現構建的時候會報錯,而且構建好的jQuery.js檔案中ES6的文法也沒有被轉換為ES5的文法。這說明構建原始碼的時候並沒有啟用Babel。

我們在來看Babel在Grunt裡面的配置

babel: {    options: {        sourceMap: "inline",        retainLines: true    },    nodeSmokeTests: {        files: {            "test/node_smoke_tests/lib/ensure_iterability.js":            "test/node_smoke_tests/lib/ensure_iterability_es6.js"        }    }},

可以看出,Babel僅是將測試案例中的煙霧測試 (Smoke Test)用例做了轉換,而原始碼則不在被轉換列表中。

 

提問:jQuery的原始碼用的是AMD規範做模組化,為什麼最終構建好的代碼卻沒有AMD的語句呢?

答:閱讀jQuery的原始碼,我們可以很清楚的看到AMD規範的語句。

然後在dist裡面的構建好的檔案中,我們卻找不到AMD規範語句的影子,jQuery是如何去掉了這些AMD語句呢?起初筆者認為是用了一些Grunt上的外掛程式,後來閱讀了build裡面的代碼才發現,是在build裡面使用正則將AMD語句去除。jQuery雖然是用的AMD做模組化,但是具體的代碼結構還是有自己的一套策略,這個應該就是為了最後構建代碼而考慮的。

src的根目錄下,共有20多個js檔案,很多js檔案都有同名的目錄與之對應。目錄之中最特別的目錄就是var目錄,因為var目錄並不存在與之對應的名為var.js的檔案。

var這個名字和js的關鍵字var相同,這和這個目錄這樣命名肯定是有關係的。沒錯,jQuery在去除AMD語句的時候,發現如果是var目錄裡的檔案的話,就會將其轉換為“var 檔案名稱 = AMD輸出的對象”的形式。如:

define( ‘var/arr‘,[],function() {    "use strict";    return [];} );define( ‘var/document‘,[],function() {    "use strict";    return window.document;} );define( ‘var/getProto‘,[],function() {    "use strict";    return Object.getPrototypeOf;} );......

原始碼的這幾個模組最終會把構建為:

var arr = [];var document = window.document;var getProto = Object.getPrototypeOf;
......

而對於非“var”目錄下的模組,jQuery會將define關鍵字等AMD相關的語句直接移除。其中sizzle模組更為特殊,jQuery在構建的時候還做了更多的操作,這裡就不再細究了。

分析到這大家也能看出,jQuery這樣構建是會破壞AMD各個模組的範圍的。我們之所以需要模組化我們的代碼,一點是不希望我們把我們的內部(私人)變數聲明到全域範圍中,而JavaScript是一種函數級範圍的語言,jQuery在構建的時候去掉了AMD的函數形式,這樣所有模組的代碼構建後的都會在同一個範圍裡,所以在修改jQuery原始碼的時候一定要小心,不要在範圍裡面隨意建立相同名稱的變數,防止造成模組間的衝突。

以上就是jQuery去除AMD的過程。

 

瞭解了jQuery的構建過程後,我們就可以輕鬆愉快地瀏覽jQuery的原始碼了。事實上如果jQuery構建的時候採用webpack這樣的工具就簡單多了。jQuery沒有採用這樣的工具可能也是曆史原因,或者是出於進一步最佳化代碼的目的。

問答形式閱讀jQuery源碼(一)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.