1. 程式人生 > >AMD、CMD、UMD

AMD、CMD、UMD

介紹 多年來,可供選擇的JavaScript元件的生態系統不斷地穩步增加。有很多的選擇固然是很好的一件事,但是各個元件混合搭配使用的時候會帶來不少的問題,開發者不會花很多時間就會發現所有元件使用起來總有這樣那樣的問題。 為了解決這些問題,互為競爭對手的模組規範 AMD 和 CommonJS 出現了,它們可以讓開發者在約定的沙箱以模組化的方式編寫自己的程式碼,以免“汙染生態系統”。 AMD 非同步模組定義(英文簡稱AMD)已經引領了前端潮流,RequireJS已經是最流行的實現方式。 下面的例子是  foo模組簡單地依賴 jquery。
define(['jquery'], function ($) { 
    function myFunc(){}; 
return myFunc; });

 

下面的更復雜一點的例子就是多個依賴和多個暴露方法的用法。
define(['jquery', 'underscore'], function ($, _) { 
function a(){}; function b(){}; function c(){};
return { b:b, c:c } });

 

定義的第一部分是依賴的陣列,而第二部分基本上是僅在第一部分宣告好才能執行的回撥函式。(像 RequireJS 這種指令碼載入器才會關心這部分,包括找出依賴檔案的位置) 注意:定義中的依賴順序很重要!(比如  jQuery--->$,underscore--->_) 還要注意的是,我們可以對映依賴到我們想要的變數上。如果我們將上面程式碼中的 $改為$,那我們下面程式碼的函式塊中引用到jQuery時都得用$代替$。 最重要的一點是:你絕對不能在上述程式碼外的函式中引用變數 $和_,因為它對於外面來說就是一個不透明的沙箱。這就是那些規範想要達到的目標!
CommonJS 如果你用過  Node.js寫過程式碼,那你會對CommonJS感到熟悉(因為就是隻有一些輕微的變動)。它已經變成使用Browserify開發的前端開發者中的一種趨勢。 用跟上面一樣的格式,下面就是採用 CommonJS規範的foo模組寫法。
var $ = require('jquery'); 
function myFunc(){
    //...
}; 
module.exports = myFunc;

 

下面是應用了多依賴和多個暴露方法的複雜例子:
var $ = require('jquery');
var _ = require('underscore');

function a(){};    
function b(){};    
function c(){};   

module.exports = {
    b: b,
    c: c
};

 

UMD: 通用模組定義 雖然 CommonJS和AMD的風格同樣大受歡迎,但是看起來似乎它們並沒有達成共識。這樣的局面也導致了一種能同時支援兩種風格的需要出現,這帶給了我們通用模組定義。 下面這種模式誠然醜陋,但是能使 AMD和CommonJS和諧相處,還支援老式的global變數定義。
(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD
        define(['jquery'], factory);
    } else if (typeof exports === 'object') {
        // Node, CommonJS-like
        module.exports = factory(require('jquery'));
    } else {
        // Browser globals (root is window)
        root.returnExports = factory(root.jQuery);
    }
}(this, function ($) {
    //    methods
    function myFunc(){};

    //    exposed public method
    return myFunc;
}));

 


保持同樣的模式實現更復雜的例子:
(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD
        define(['jquery', 'underscore'], factory);
    } else if (typeof exports === 'object') {
        // Node, CommonJS-like
            module.exports = factory(require('jquery'), require('underscore'));
    } else {
        // Browser globals (root is window)
        root.returnExports = factory(root.jQuery, root._);
    }
}(this, function ($, _) {
    //    methods
    function a(){};    //    private because it's not returned (see below)
    function b(){};    //    public because it's returned
    function c(){};    //    public because it's returned

    //    exposed public methods
    return {
        b: b,
        c: c
    }
}));