CommonJS,AMD,CMD規範

1、模塊

模塊化:是一種處理複雜系統分解爲代碼結構更合理,可維護性更高的可管理的模塊的方式。前端

在理想狀態下咱們只須要完成本身部分的核心業務邏輯代碼,其餘方面的依賴能夠經過直接加載被人已經寫好模塊進行使用便可。jquery

無模塊es6

<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>

優勢:
相比於使用一個js文件,這種多個js文件實現最簡單的模塊化的思想是進步的。 編程

缺點:
污染全局做用域。 由於每個模塊都是暴露在全局的,簡單的使用,會致使全局變量命名衝突,固然,咱們也可使用命名空間的方式來解決。
對於大型項目,各類js不少,開發人員必須手動解決模塊和代碼庫的依賴關係,後期維護成本較高。
依賴關係不明顯,不利於維護。 好比main.js須要使用jquery,可是,從上面的文件中,咱們是看不出來的,若是jquery忘記了,那麼就會報錯。api

2、CommonJs

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 解決方案。瀏覽器

3、AMD

AMD 即 Asynchronous Module Definition,中文名是異步模塊定義的意思。它是一個在瀏覽器端模塊化開發的規範緩存

AMD也採用require()語句加載模塊,可是不一樣於CommonJS,它要求兩個參數:服務器

require([module], callback);
第一個參數[module],是一個數組,裏面的成員就是要加載的模塊;第二個參數callback,則是加載成功以後的回調函數。若是將前面的代碼改寫成AMD形式,就是下面這樣:curl

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}
});

第一個參數 id 爲字符串類型,表示了模塊標識,爲可選參數。若不存在則模塊標識應該默認定義爲在加載器中被請求腳本的標識。若是存在,那麼模塊標識必須爲頂層的或者一個絕對的標識。
第二個參數,dependencies ,是一個當前模塊依賴的,已被模塊定義的模塊標識的數組字面量。
第三個參數,factory,是一個須要進行實例化的函數或者一個對象。
建立模塊標識爲 Module1 的模塊,依賴於 require, export,和標識爲 beta 的模塊

AMD規範容許輸出模塊兼容CommonJS規範,這時define方法以下:

define(function (require, exports, module) {
    
    var reqModule = require("./someModule");
    requModule.test();
    
    exports.asplode = function () {
        //someing
    }
});

優勢:

適合在瀏覽器環境中異步加載模塊。能夠並行加載多個模塊。 缺點:

提升了開發成本,而且不能按需加載,而是必須提早加載全部的依賴。

4、CMD

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打包,模塊的加載邏輯偏重。

    5、 ES6 模塊

    CommonJS
    對於基本數據類型,屬於複製。即會被模塊緩存。同時,在另外一個模塊能夠對該模塊輸出的變量從新賦值。
    對於複雜數據類型,屬於淺拷貝。因爲兩個模塊引用的對象指向同一個內存空間,所以對該模塊的值作修改時會影響另外一個模塊。
    當使用require命令加載某個模塊時,就會運行整個模塊的代碼。
    當使用require命令加載同一個模塊時,不會再執行該模塊,而是取到緩存之中的值。也就是說,CommonJS模塊不管加載多少次,都只會在第一次加載時運行一次,之後再加載,就返回第一次運行的結果,除非手動清除系統緩存。
    循環加載時,屬於加載時執行。即腳本代碼在require的時候,就會所有執行。一旦出現某個模塊被"循環加載",就只輸出已經執行的部分,還未執行的部分不會輸出。
    ES6模塊
    ES6模塊中的值屬於【動態只讀引用】。
    對於只讀來講,即不容許修改引入變量的值,import的變量是隻讀的,不管是基本數據類型仍是複雜數據類型。當模塊遇到import命令時,就會生成一個只讀引用。等到腳本真正執行時,再根據這個只讀引用,到被加載的那個模塊裏面去取值。
    對於動態來講,原始值發生變化,import加載的值也會發生變化。不管是基本數據類型仍是複雜數據類型。
    循環加載時,ES6模塊是動態引用。只要兩個模塊之間存在某個引用,代碼就可以執行
    原文連接: https://cloud.tencent.com/developer/article/1177217

相關文章
相關標籤/搜索