Skip to content
uupaa edited this page Jun 8, 2015 · 69 revisions

このエントリでは、WebModule に使われている 実装パターン(WebModulePattern) について紹介しています。

WebModulePattern は、どこでも動作し見通しの良いモジュールを記述するためのコードパターンです。 以下のように記述すると、Browser, Node.js, Worker, NW.js で動作するモジュールを構築できます。

名前空間

WebModule における GLOBAL とは JavaScript のルート要素(window や self, global)を示す定数です。この値は WebModuleIdiom を使って導き出されます。

WebModulePattern を使って定義したモジュールは GLOBAL 直下ではなく、GLOBAL.WebModule 名前空間の下に export されます。

パターン

以下は、モジュールを定義する部分のコードを抜粋したものです。
function MyExample() { ... }GLOBAL.WebModule.MyExample として export されます。

(function moduleExporter(name, closure) {
    "use strict";

    var entity = GLOBAL["WebModule"]["exports"](name, closure);

    // Node.js 用に export
    if (typeof module !== "undefined") {
        module["exports"] = entity;
    }

    // entity の 初期化処理
    //

    return entity;

})("MyExample", function moduleClosure(global) {
    "use strict";

    function MyExample() { ... }

    return MyExample; // return entity
});

共通コード

GLOBAL を導き出すコードGLOBAL.WebModule.exports 関数などの共通コードは、別ファイル(WebModule.js)に記述し、MyExample.js より先にロードしておきます。

// http://git.io/WebModule

// --- global variables ------------------------------------
// https://github.com/uupaa/WebModule/wiki/WebModuleIdiom
var GLOBAL = GLOBAL || (this || 0).self || global;

// --- environment detection -------------------------------
GLOBAL["IN_NODE_OR_NW"] = !!GLOBAL.global;
GLOBAL["IN_BROWSER"]    = !GLOBAL["IN_NODE_OR_NW"] && "document" in GLOBAL;
GLOBAL["IN_WORKER"]     = !GLOBAL["IN_NODE_OR_NW"] && "WorkerLocation" in GLOBAL;
GLOBAL["IN_NODE"]       =  GLOBAL["IN_NODE_OR_NW"] && !/native/.test(setTimeout);
GLOBAL["IN_NW"]         =  GLOBAL["IN_NODE_OR_NW"] &&  /native/.test(setTimeout);

// --- validate and assert functions -----------------------
//{@dev https://github.com/uupaa/WebModule/wiki/Validate
GLOBAL["$type"]  = function(value, types)                 { return GLOBAL["Valid"] ? GLOBAL["Valid"].type(value, types) : true; };
GLOBAL["$keys"]  = function(value, keys)                  { return GLOBAL["Valid"] ? GLOBAL["Valid"].keys(value, keys)  : true; };
GLOBAL["$some"]  = function(value, candidate, ignoreCase) { return GLOBAL["Valid"] ? GLOBAL["Valid"].some(value, candidate, ignoreCase) : true; };
GLOBAL["$args"]  = function(api, args)                    { if (GLOBAL["Valid"]) { GLOBAL["Valid"].args(api, args); } };
GLOBAL["$valid"] = function(value, api, highlihgt)        { if (GLOBAL["Valid"]) { GLOBAL["Valid"](value, api, highlihgt); } };
//}@dev

// --- WebModule ------------------------------------------
GLOBAL.WebModule = {
    exports: function(name, closure) {
        var alias = name in GLOBAL["WebModule"] ? (name + "_") : name;

        return alias in this ? this[alias]
                             : this[alias] = closure(GLOBAL);
    }
};

古いスタイルで書かれたコードを WebModulePattern に書き直す方法 についても参照してください。

ES6::Modules への対応

TBD: このセクションは推敲や検証が終わっていません。

WebModulePattern で書かれたコードを ES6::Modules の export に対応させるには先頭に1行追加します。

export       // この行を追加
(function moduleExporter(name, closure) {
    "use strict";

    :

    return entity;

})("MyExample", function moduleClosure(global) {

    function MyExample() { ... }

    return MyExample; // return entity
});

Clone this wiki locally