天天看點

CommonJS, AMD, CMD的差別

CommonJS, AMD, CMD都是JS子產品化的規範。

CommonJS是伺服器端js子產品化的規範,NodeJS是這種規範的實作。

AMD(異步子產品定義)和CMD(通用子產品定義)都是浏覽器端js子產品化的規範。RequireJS 遵循的是 AMD,SeaJS 遵循的是 CMD。

一 、CommonJS

根據CommonJS規範,一個單獨的檔案就是一個子產品。加載子產品使用require方法,該方法讀取一個檔案并執行,最後傳回檔案内部的exports對象。是以,定義一個子產品就是寫一個新的js檔案,但是最後要将檔案的内容exports出來。接下來我們看一下如何定義子產品和加載子產品。

//定義一個module.js檔案加粗樣式
var A = function() {
    console.log('我是定義的子產品');
}
//導出這個子產品
//1.第一種傳回方式 module.exports = A; 
//2.第二種傳回方式 module.exports.test = A
//3.第三種傳回方式 exports.test = A;
exports.test = A;



//再寫一個test.js檔案,去調用剛才定義好的子產品,這兩個檔案在同一個目錄下
var module = require("./module");  //加載這個子產品

//調用這個子產品,不同的傳回方式用不同的方式調用
//1.第一種調用方式 module();
//2.第二種調用方式 module.test();
//3.第三種調用方式 module.test();
module.test();


//接下來我們去執行這個檔案,前提是你本地要安裝node.js,不多說了,自己百度安裝。
//首先打開cmd, cd到這兩個檔案所在的目錄下,執行: node test.js
node test.js
//輸出結果:我是定義的子產品

           

當我們執行 node test.js 的時候,根據 var module = require("./module"); 會加載同一目錄下的module.js檔案,并将這個檔案的exports對象傳回,指派給module,是以我們調用 module.test(); 就相當于執行了module.js檔案。

以上就是CommonJS規範下的子產品定義與加載的形式。

CommonJS 加載子產品是同步的,是以隻有加載完成才能執行後面的操作。像Node.js主要用于伺服器的程式設計,加載的子產品檔案一般都已經存在本地硬碟,是以加載起來比較快,不用考慮異步加載的方式,是以CommonJS規範比較适用。但如果是浏覽器環境,要從伺服器加載子產品,這是就必須采用異步模式。是以就有了 AMD CMD 解決方案。

二 、AMD(異步子產品定義)

AMD規範通過define方法去定義子產品,通過require方法去加載子產品。RequireJS實作了這種規範。

AMD隻有一個接口:define(id?,dependencies?,factory); 它要在聲明子產品的時候制定所有的依賴(dep),并且還要當做形參傳到factory中。要是沒什麼依賴,就定義簡單的子產品(或者叫獨立的子產品),下面我們看代碼實作:

//編寫一個module1.js檔案
//定義獨立的子產品
define({
    methodA: function() {
        console.log('我是module1的methodA');    
    },
    methodB: function() {
        console.log('我是module1的methodB');    
    }
});



//編寫一個module2.js檔案
//另一種定義獨立子產品的方式
define(function () {
    return {
        methodA: function() {
            console.log('我是module2的methodA');    
        },
        methodB: function() {
            console.log('我是module2的methodB');    
        }
    };
});



//編寫一個module3.js檔案
//定義非獨立的子產品(這個子產品依賴其他子產品)
define(['module1', 'module2'], function(m1, m2) {
    return {
        methodC: function() {
            m1.methodA();
            m2.methodB();
        }
    };

});



//再定義一個main.js,去加載這些個子產品
require(['module3'], function(m3){
    m3.methodC();
});


//我們在一個html檔案中去通過RequireJS加載這個main.js
//等号右邊的main指的main.js
<script data-main="main" src="require.js"></script>

//浏覽器控制台輸出結果
我是module1的methodA
我是module2的methodB

           

三、CMD(通用子產品定義)

CMD是SeaJS 在推廣過程中對子產品定義的規範化産出。

AMD和CMD的差別:

  1. 對于依賴的子產品,AMD 是提前執行,CMD 是延遲執行。不過 RequireJS 從 2.0 開始,也改成可以延遲執行(根據寫法不同,處理方式不同)。CMD 推崇 as lazy as possible(盡可能的懶加載,也稱為延遲加載,即在需要的時候才加載)。
  2. CMD 推崇依賴就近,AMD 推崇依賴前置。雖然 AMD 也支援 CMD 的寫法,同時還支援将 require 作為依賴項傳遞,但 RequireJS 的作者預設是最喜歡上面的寫法,也是官方文檔裡預設的子產品定義寫法。看代碼:
// CMD
define(function(require, exports, module) {
    var a = require('./a');
    a.doSomething();
    // 此處略去 100 行
    var b = require('./b');   // 依賴可以就近書寫
    b.doSomething();
    // ... 
})

// AMD 預設推薦的是
define(['./a', './b'], function(a, b) { // 依賴必須一開始就寫好
    a.doSomething();
    // 此處略去 100 行
    b.doSomething();
    //...
})
           
  1. AMD 的 API 預設是一個當多個用,CMD 的 API 嚴格區分,推崇職責單一。比如 AMD 裡,require 分全局 require 和局部 require,都叫 require。CMD 裡,沒有全局 require,而是根據子產品系統的完備性,提供 seajs.use 來實作子產品系統的加載啟動。CMD 裡,每個 API 都簡單純粹。

繼續閱讀