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

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

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

WebModulePattern

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

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

    function MyExample() { ... }

    return MyExample; // return entity
});

モジュールの実体(entity, この場合は function MyExample() { ... }) に対して何か追加で行う場合や、GLOBAL.WebModule に依存したくない場合は、クロージャ関数(この例では moduleExporter と moduleClosure) を追加で導入し、以下のように記述してください。

(function moduleExporter(moduleName, moduleClosure) { // http://git.io/WebModule
    "use strict";

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

    // entity に対する操作

    return entity;

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

    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