天天看點

JavaScript子產品化規範commonJs、AMD、CMD一、CommonJS二、AMD三、CMD四、AMD+CMD比較

一、CommonJS

CommonJS 原來叫 ServerJS,是以在浏覽器環境之外建構 JavaScript 生态系統為目标而産生的項目,比如在伺服器

和桌面環境中。

CommonJS 規範是為了解決 JavaScript 的作用域問題而定義的子產品形式,可以使每個子產品它自身的命名空間中執行。

該規範的主要内容是,子產品必須通過 module.exports 導出對外的變量或接口,通過 require() 來導入其他子產品的輸出到目前子產品作用域中。例子如下:

// moduleA.js
module.exports = function(x) {
    return x * x; 
};
           
// moduleB.js
const moduleA = require('./moduleA');
var result = moduleA();
           

CommonJS 是同步加載子產品。

NodeJs就是采用commonJs規範。

二、AMD

AMD(Asynchronous Module Definition)(異步子產品定義)是為浏覽器環境設計的,因為 CommonJS 子產品系統是同步加載的,目前浏覽器環境還沒有準備好同步加載子產品的條件。

AMD 定義了一套 JavaScript 子產品依賴異步加載标準,來解決同步加載的問題。

子產品通過 define 函數定義在閉包中,格式如下:

define(id?: String, dependencies?: String[], factory: Function|Object);
           

id 是子產品的名字,它是可選的參數。

dependencies 指定了所要依賴的子產品清單,它是一個數組,也是可選的參數,每個依賴的子產品的輸出将作為參數一次傳入 factory 中。如果沒有指定 dependencies,那麼它的預設值是 [“require”, “exports”, “module”]。

define(function(require, exports, module) {})
           

factory 是最後一個參數,它包裹了子產品的具體實作,它是一個函數或者對象。如果是函數,那麼它的傳回值就是子產品的輸出接口或值。

定義一個名為 moduleA 的子產品,它依賴 jQuery 子產品:

define('moduleA', ['jquery'], function($) {
    // $ 是 jquery 子產品的輸出
    $('body').text('hello world');
});
// 使用
define(['moduleA'], function(moduleA) {});
           

RequireJS就是采用AMD規範。

三、CMD

CMD(Common Module Definition),在 CMD 規範中,一個子產品就是一個檔案。

代碼的書寫格式如下:

define(factory);
           

define是全局函數,用來定義子產品。define接收factory參數,factory可以是函數,對象或字元串。

factory為對象或字元串時,表示該子產品的接口就是該對象或字元串,比如要定義一個json資料子產品:

define({"key" : "val"});
           

也可以通過字元串定義模闆子產品:

define("Hello {{name}}!")
           

factory是函數時,表示是子產品的構造方法。執行該構造方法,可以得到子產品對外提供的接口,factory方法在執行時,預設會傳入三個參數,require,exports,module。

define(function(require, exports, module) {
    // 需要導出的子產品
});
           

require是方法,接收模闆辨別作為唯一參數,用來擷取其他子產品提供的接口:

define(function(require, exports) {
    const a = require('./a');
    a.doSomething();
});
           

require是同步往下執行的,require.async(id, callback?)用來在子產品内部異步加載子產品,并在加載完後執行回調函數:

define(function(require, exports) {
    require.async(['./a', './b'], function(c, d) {
        c.doSomething();
        d.doSomething();
    });
});
           

factory是函數時的第二個參數exports,exports是一個對象,用來對外提供子產品接口。

define(function(require, exports) {
    exports.str = 'xxxxx';  // 對外提供str屬性

    exports.doSomething = function() {  // 對外提供 doSomething() 方法
        // TODO
    };
});
           

除了exports外,還可以用return直接對外提供對象接口

define(function(require, exports) {
    return {
        str : 'xxxxx' ,
        doSomething : function() {}
    };
});
           

exports是module.exports對象的一個引用,很多時候exports都無法滿足要求,例如對外提供一個執行個體對象:

define(function(require, exports, module) {
    function Person(name, age) {
        this.name = name;
        this.age = age;
    }
    module.exports = new Person('lily', ); // 對外提供執行個體化後的Person對象。
});
           

module.exports還可以對外提供一個函數(exports不可以):

define(function(require, exports, module) {
    var Person = function(name, age) {
        this.name = name;
        this.age = age;
    }
    module.exports = Person; // 對外提供Person函數。
});
           

sea.js就是采用CMD規範。

四、AMD+CMD比較

AMD預設是依賴前置,在一開始就将需要依賴的檔案配置并加載好:

define('moduleA', ['jquery'], function($) {
    // 依賴的配置檔案已經配置并加載好了。
    $('body').text('hello world');
});
           

CMD是依賴就近,需要使用的時候才會去配置加載:

define(function(require, exports) {
    var a = require('./a.js'); // 配置并加載,同步

    if(false) {
        var b = require('./b.js'); // 該配置的檔案永遠不會去加載,
    }
});
           

繼續閱讀