JavaScript初衷:實現簡單的頁面交互邏輯,寥寥數語便可;javascript
隨着web2.0時代的到來,Ajax技術獲得普遍應用,jQuery等前端庫層出不窮,前端代碼日益膨脹html
問題:前端
這時候JavaScript做爲嵌入式的腳本語言的定位動搖了,JavaScript卻沒有爲組織代碼提供任何明顯幫助,甚至沒有類的概念,JavaScript極其簡單的代碼組織規範不足以駕馭如此龐大規模的代碼java
模塊化:是一種處理複雜系統分解爲代碼結構更合理,可維護性更高的可管理的模塊的方式。node
在理想狀態下咱們只須要完成本身部分的核心業務邏輯代碼,其餘方面的依賴能夠經過直接加載被人已經寫好模塊進行使用便可。jquery
無模塊git
<script src="jquery.js"></script> <script src="jquery_scroller.js"></script> <script src="main.js"></script> <script src="other1.js"></script> <script src="other2.js"></script> <script src="other3.js"></script>
優勢:github
相比於使用一個js文件,這種多個js文件實現最簡單的模塊化的思想是進步的。 web
缺點:編程
污染全局做用域。 由於每個模塊都是暴露在全局的,簡單的使用,會致使全局變量命名衝突,固然,咱們也可使用命名空間的方式來解決。
對於大型項目,各類js不少,開發人員必須手動解決模塊和代碼庫的依賴關係,後期維護成本較高。
依賴關係不明顯,不利於維護。 好比main.js須要使用jquery,可是,從上面的文件中,咱們是看不出來的,若是jquery忘記了,那麼就會報錯。
CommonJs 是服務器端模塊的規範,Node.js採用了這個規範。
根據CommonJS規範,一個單獨的文件就是一個模塊。加載模塊使用require方法,該方法讀取一個文件並執行,最後返回文件內部的exports對象。
var math = require('math'); math.add(2, 3);
第二行math.add(2, 3),在第一行require('math')以後運行,所以必須等math.js加載完成。也就是說,若是加載時間很長,整個應用就會停在那裏等。您會注意到 require
是同步的。
CommonJS 加載模塊是同步的,因此只有加載完成才能執行後面的操做。像Node.js主要用於服務器的編程,加載的模塊文件通常都已經存在本地硬盤,因此加載起來比較快,不用考慮異步加載的方式,因此CommonJS規範比較適用。但若是是瀏覽器環境,要從服務器加載模塊,這是就必須採用異步模式。因此就有了 AMD CMD 解決方案。
AMD 即 Asynchronous Module Definition,中文名是異步模塊定義的意思。它是一個在瀏覽器端模塊化開發的規範
AMD也採用require()語句加載模塊,可是不一樣於CommonJS,它要求兩個參數:
require([module], callback);
第一個參數[module],是一個數組,裏面的成員就是要加載的模塊;第二個參數callback,則是加載成功以後的回調函數。若是將前面的代碼改寫成AMD形式,就是下面這樣:
require(['math'], function (math) { math.add(2, 3); });
math.add()與math模塊加載不是同步的,瀏覽器不會發生假死。因此很顯然,AMD比較適合瀏覽器環境。目前,主要有兩個Javascript庫實現了AMD規範:require.js和curl.js。
與 RequireJS
AMD 是 RequireJS 在推廣過程當中對模塊定義的規範化產出
AMD異步加載模塊。它的模塊支持對象 函數 構造器 字符串 JSON等各類類型的模塊。
//經過數組引入依賴 ,回調函數經過形參傳入依賴 define(['Module1', ‘Module2’], function (Module1, Module2) { function foo () { /// someing Module1.test(); } return {foo: foo} });
AMD規範容許輸出模塊兼容CommonJS規範,這時define方法以下:
define(function (require, exports, module) { var reqModule = require("./someModule"); requModule.test(); exports.asplode = function () { //someing } });
優勢:
適合在瀏覽器環境中異步加載模塊。能夠並行加載多個模塊。
缺點:
提升了開發成本,而且不能按需加載,而是必須提早加載全部的依賴。
CMD是SeaJS 在推廣過程當中對模塊定義的規範化產出
CMD和AMD的區別有如下幾點:
1.對於依賴的模塊AMD是提早執行,CMD是延遲執行。不過RequireJS從2.0開始,也改爲能夠延遲執行(根據寫法不一樣,處理方式不經過)。
2.AMD推崇依賴前置(在定義模塊的時候就要聲明其依賴的模塊),CMD推崇依賴就近(只有在用到某個模塊的時候再去require——按需加載)。
//AMD define(['./a','./b'], function (a, b) { //依賴一開始就寫好 a.test(); b.test(); }); //CMD define(function (requie, exports, module) { //依賴能夠就近書寫 var a = require('./a'); a.test(); ... //軟依賴 if (status) { var b = requie('./b'); b.test(); } });
3.AMD的api默認是一個當多個用,CMD嚴格的區分推崇職責單一。例如:AMD裏require分全局的和局部的。CMD裏面沒有全局的 require,提供 seajs.use()來實現模塊系統的加載啓動。CMD裏每一個API都簡單純粹。
AMD 是 RequireJS 在推廣過程當中對模塊定義的規範化產出,CMD是SeaJS 在推廣過程當中被普遍認知。RequireJs出自dojo加載器的做者James Burke,SeaJs出自國內前端大師玉伯。兩者的區別,玉伯在12年如是說:
RequireJS 和 SeaJS 都是很不錯的模塊加載器,二者區別以下:
1. 二者定位有差別。RequireJS 想成爲瀏覽器端的模塊加載器,同時也想成爲 Rhino / Node 等環境的模塊加載器。SeaJS 則專一於 Web 瀏覽器端,同時經過 Node 擴展的方式能夠很方便跑在 Node 服務器端
2. 二者遵循的標準有差別。RequireJS 遵循的是 AMD(異步模塊定義)規範,SeaJS 遵循的是 CMD (通用模塊定義)規範。規範的不一樣,致使了二者API 的不一樣。SeaJS 更簡潔優雅,更貼近 CommonJS Modules/1.1 和 Node Modules 規範。
3. 二者社區理念有差別。RequireJS 在嘗試讓第三方類庫修改自身來支持 RequireJS,目前只有少數社區採納。SeaJS 不強推,而採用自主封裝的方式來「海納百川」,目前已有較成熟的封裝策略。
4. 二者代碼質量有差別。RequireJS 是沒有明顯的 bug,SeaJS 是明顯沒有 bug。
5. 二者對調試等的支持有差別。SeaJS 經過插件,能夠實現 Fiddler 中自動映射的功能,還能夠實現自動 combo 等功能,很是方便便捷。RequireJS無這方面的支持。
6. 二者的插件機制有差別。RequireJS 採起的是在源碼中預留接口的形式,源碼中留有爲插件而寫的代碼。SeaJS 採起的插件機制則與 Node 的方式一致開放自身,讓插件開發者可直接訪問或修改,從而很是靈活,能夠實現各類類型的插件。
優勢:
一樣實現了瀏覽器端的模塊化加載。
能夠按需加載,依賴就近。
缺點:
依賴SPM打包,模塊的加載邏輯偏重。
CommonJS
ES6模塊
參考: