這是一篇關於javascript模組化AMD,CMD,CommonJS的學習總結,作為記錄也給同樣對三種方式有疑問的童鞋們,有不對或者偏差之處,望各位大神指出,不勝感激。
本篇預設讀者大概知道require,seajs的用法(AMD,CMD用法),所以沒有加入使用語法。
1、為何而生:
這三個規格都是為javascript模組化加載而生的,都是在用到或預計要用到某些模組時候加載該模組,使得大量的系統巨大的龐雜的程式碼得以很好的組織和管理。模組化使得我們在使用和管理程式碼的時候不那麼混亂,也方便了多人的合作。
2、那些規範們:
(1)、CommonJS 是一個有志於建構 JavaScript 生態圈的組織。整個社群致力於提高 JavaScript 程式的可攜性和可交換性,無論是在服務端還是瀏覽器端。
a group with a goal of building up the JavaScript ecosystem for web servers, desktop and command line apps and in the browser.
一個有目標的建置JavaScript生態系統Web伺服器群組,在瀏覽器和命令列應用程式和桌面。 (他自己wiki上這麼說的)
這個組織呢制定了一些規範 (可以去他們網站看看 http://www.commonjs.org/)包括CommonJS Modules/1.0 規範,我們平常所說的commonjs規範,說的就是這個了。
「The CommonJS API will fill that gap by defining APIs that handle many common application needs, ultimately providing a standard library as rich as those of Python, Ruby and Java. 」--(http://www.com)-- org/)
所以說Commonjs是一個比較偏向伺服器端的規格。 Node.js採用了這個規範。 根據CommonJS規範,一個單獨的檔案就是一個模組。載入模組使用require方法,方法讀取 取一個檔案並執行,最後傳回檔案內部的exports物件。
他又說了,可以用在下面這些場景 ,所以他更明顯的偏向伺服器端。當然你也可以把它用在瀏覽器裡邊(他們自己說可以)。
•Server-side JavaScript applications
•Command line tools
•Desktop GUI-based applications
•Hybrid applications (Titanium, Adobe AIR)
(2)、AMD規範
Commonjs解決了模組化的問題,並且可以用在瀏覽器中,但是Commonjs是同步載入模組,當要用到該模組了,現載入現用,這種同步機製到了瀏覽器裡邊就有問題了,載入速度啊啥的(覽器同步載入模組會導致效能、可用性、偵錯和跨網域存取等問題)。
鑑於瀏覽器的特殊情況,又出現了一個規範,這個規範呢可以實現異步加載依賴模組,並且會提前加載那就是AMD規範。 AMD可以作為CommonJS模組一個中轉的版本只要CommonJS沒有被用來同步的require呼叫。使用同步require呼叫的CommonJS程式碼可以轉換為使用回呼風格的AMD模組載入器(https://github.com/amdjs/amdjs-api/wiki/AMD-(%E4%B8%AD%E6%96% 87%E7%89%88) (它所說的)。
下面是一個使用了簡單CommonJS轉換的模組定義(它是amd規範的一種用法):
});
所以說AMD和Commonjs是相容的,只要稍稍調換一下調用方法就實現了同步加載(我很懷疑amd也是在commonjs基礎上加了個殼,然後並沒有找到其他的神馬說明和支持的文字,找到了一定加到這裡)。
看一下AMD規格你會發現,AMD基本上都是提前說明依賴模組,然後預先載入這些模組,其實這就要求你事先想好這些依賴,事先寫好,不然寫程式碼過程要回到開頭繼續加入依賴。
(3)、CMD
不知道是不是針對這個問題,淘寶的玉伯大牛搞了個seajs出來,並聲稱這個規範是遵循CMD規範的,然後給出了這個規範的一個連接(打開會發現draft字樣)。關於這個規範呢玉伯在知乎是這麼說的
”AMD 是 RequireJS 在推廣過程中對模組定義的規範化產出。
CMD 是 SeaJS 在推廣過程中對模組定義的規範化產出。
類似的還有 CommonJS Modules/2.0 規範,是 BravoJS 在推廣過程中對模組定義的規範化產出。
還有不少⋯⋯
“
所以這個規範其實是為了Seajs的推廣然後搞出來的。那麼看看SeaJS是怎麼回事吧,基本上就是知道這個規範了。
同樣Seajs也是預先載入依賴js跟AMD的規範在預先載入這一點上是相同的,明顯不同的地方是調用,和聲明依賴的地方。 AMD和CMD都是用difine和require,但是CMD標準傾向於在使用過程中提出依賴,就是不管代碼寫到哪突然發現需要依賴另一個模組,那就在當前代碼用require引入就可以了,規範會幫你搞定預先加載,你隨便寫就可以了。但AMD標準讓你必須提前在頭部依賴參數部分寫好(沒有寫好?倒回去寫好咯)。這就是最明顯的差別。
3.共生共處
由於CommonJS是伺服器端的規範,更另外兩個標準實際上不衝突。
AMD在國外用的更多,當然國內也是不少的,jQuery1,7版本開始使用,Dojo在1.6版本開始用,這已經能夠證明它足夠牛x了。
CMD當然也有很多人在用,但是基本上都集中在國內,Seajs官網就展示了一大堆牛逼的公司在用(包括愛奇藝,騰訊微博,支付寶,淘寶等一大堆,去這裡看看http://seajs.org/docs/),估計小的不出名的也不計其數了,畢竟很多公司招聘都要求會seajs嘛。
所以三個規範目前都挺好(其實也主要是因為js麼有自己的模組載入機制,es6出來之後不知道會怎樣)。
當我們寫一個檔案需要與不同的載入規範相容的時候怎麼辦呢,看看下面的程式碼。
(function (root, factory) { if (typeof define === 'function' && define.amd) { // AMD define(['jquery', 'underscore'], factory); } else if (typeof exports === 'object') { // Node, CommonJS之类的 module.exports = factory(require('jquery'), require('underscore')); } else { // 浏览器全局变量(root 即 window) root.returnExports = factory(root.jQuery, root._); } }(this, function ($, _) { // 方法 function a(){}; // 私有方法,因为它没被返回 (见下面) function b(){}; // 公共方法,因为被返回了 function c(){}; // 公共方法,因为被返回了 // 暴露公共方法 return { b: b, c: c } }));
這個程式碼可以相容於各種載入規範了。
4、AMD和CMD的差別
下面這幾點是玉伯在知乎上說的。
1. 對於依賴的模組,AMD 是提前執行,CMD 是延遲執行。不過 RequireJS 從 2.0 開始,也改成可以延遲執行(依寫法不同,處理方式不同)。 CMD 推崇 as lazy as possible.
2. CMD 推崇依賴就近,AMD 推崇依賴前置。
3. AMD 的 API 預設是一個當多個用,CMD 的 API 嚴格區分,推崇職責單一。例如 AMD 裡,require 分割全域 require 和局部 require,都叫 require。 CMD 裡,沒有全域 require,而是根據模組系統的完備性,提供 seajs.use 來實現模組系統的載入啟動。 CMD 裡,每個 API 都簡單純粹。
4. 還有一些細節差異,具體看這個規範的定義就好,就不多說了。
( 好吧~第四點是不多說了。。。。。。。)
5.AMD和CMD的一些相同
都有difine和require,而且呼叫方式實際上都可以加入依賴參數,也就是說都可以用提供依賴參數的方式來實現預先載入依賴模組(但不建議因為 注意:帶id 和deps 參數的define用法不屬於CMD 規範,而屬於Modules/Transport 規範。 ---來自:https://github.com/seajs/seajs/issues/242)。
AMD也可以在factory中使用require來現加載用到的模組,但是這個模組就不會預先加載,屬於用到才加載的同步加載了。
var a = require('a'); // 載入模組a
有不妥之處,歡迎斧正。
以上這篇淺析AMD CMD CommonJS規格--javascript模組化載入學習心得總結就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持腳本之家。