Skip to content
uupaa edited this page Jun 5, 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 されます。

GLOBAL["WebModule"]["exports"]("MyExample", function(global) {
    "use strict";

    function MyExample() { ... }

    return MyExample; // return entity
});

モジュールの実体(entity, この場合は function MyExample() { ... }) を使って何か操作を行う場合は、moduleExporter と moduleClosure 関数を使い、以下のように記述してください。

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

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

    // 初期化処理: 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 -----------------------
// 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); } };

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

        if (typeof exports !== "undefined") {
            module["exports"] = entity;
        }
        return entity;
    }
};

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

ES6::Modules への対応

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

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

export       // この行を追加
GLOBAL["WebModule"]["exports"]("MyExample", function(global) {
    "use strict";

    function MyExample() { ... }

    return MyExample; // return entity
});
Clone this wiki locally