JavaScriptのModuleモードを深く研究する

6071 ワード

原文の出所:http://blog.jobbole.com/40409/
ModuleモードはよくあるJavaScriptプログラミングモードです.一般的にこのモードはよく分かりますが、まだいくつかの高級な使い方があります.この文章では、Moduleモードの基礎知識と本当に重要な話題を述べます.オリジナルかもしれません.
基礎知識
まず、Moduleモード(2007年にYUIのエリックMiragliaがブログで提出した)を大体調べてみます.Moduleモードに慣れているなら、この部分をスキップして、直接に「上級モード」を読むことができます.
匿名関数クローズド
匿名関数のクローズドはJavaScriptの最高の特徴であり、一つもなく、すべてが可能になっている.匿名関数を作成して、直ちに実行します.関数内のすべてのコードは一つのクローズドにおいて実行され、クローズドは実行全体においてこれらのコードのプライベート性と状態を決定します.
(function () {
    // ... all vars and functions are in this scope only
    // still maintains access to all globals
}());
匿名関数の外側の括弧に注意してください.これはJavaScriptでfunctionで始まる文が関数宣言として一般的に考えられているからです.外の括弧を入れると関数式が作成されます.
グローバルインポート
JavaScriptには隠しグローバル変数という特徴があります.変数名が使用されると、コンパイラは、この変数のステートメントを上位に照会します.見つけられなかったらこの変数は全体として考えられます.賦課時にこのように使うと、グローバルなスコープが作成されます.これは、匿名のクローズド・パケットにグローバル変数を作成することが非常に容易であることを意味する.残念なことに、これはコードの管理が困難になります.プログラマにとっては、グローバル変数が一つのファイルで宣言されていないとよく分かりません.幸いなことに、匿名関数は私達にもう一つの選択をくれました.グローバル変数を匿名関数のパラメータによってコードに導入することができます.このようにして、より速くて綺麗です.
(function ($, YAHOO) {
// now have access to globals jQuery (as $) and YAHOO in this code
}(jQuery, YAHOO));
Moduleエクスポート
ときにはグローバル変数を使いたくないですが、彼らを宣言したいです.匿名関数の戻り値によって彼らを容易に導き出すことができる.Moduleモードの基本内容はこれだけです.ここにはちょっと複雑な例があります.
var MODULE = (function () {
    var my = {},
    privateVariable = 1;
    function privateMethod() {
        // ...
    }
    my.moduleProperty = 1;
    my.moduleMethod = function () {
        // ...
    };
    return my;
}());
ここでは、一つの大域的なmoduleをMODULEといい、二つの公有属性があります.一つはMODLE.moduleMethodという方法とMODLE.modulePropertyという変数です.また、彼は匿名関数のクローズドによってプライベートな内部状態を維持します.もちろん、前述のパターンを使用して、必要なグローバル変数を簡単に導入することもできます.
詳細モード
前に述べた内容は多くの需要を満たすことができますが、このようなモードをより深く研究して、強力な拡張可能な構造を作ることができます.少しずつ、MODULEというmoduleを通して勉強しましょう.
広く開拓する
現在、moduleモードの限界はmodule全体が一つのファイルに書かれている必要があります.大規模なコード開発を行った人は、一つのファイルを複数のファイルに分離することの重要性を知っています.幸運なことに、私たちは良い方法でモデルズを開拓しています.まずmoduleを導入して、属性を追加して、最後にそれをエクスポートします.ここのこの例は、上記のような方法でMODULEを開拓します.
var MODULE = (function (my) {
    my.anotherMethod = function () {
        // added method...
    };
 
    return my;
}(MODULE));
必要はありませんが、一貫性のために再びvarキーワードを使います.コードを実行すると、MODLE.another Methodという共有方法が追加されます.この拡張ファイルもまた、プライベートの内部状態と導入を維持しています.
松の広がり
上記の例は先にmoduleを作成してmoduleを開拓する必要があります.これは必要ではありません.非同期ローディングスクリプトはJavascriptのアプリケーション性能を向上させる最良の方法の一つである.松の開拓を通じて、私達は柔軟なものを創建して、任意の順序でロードすることができて、複数のファイルのmoduleに分けます.各ファイルの構造は大体以下の通りです.
var MODULE = (function (my) {
    // add capabilities...
 
    return my;
}(MODULE || {}));
このモードでは、var文が必要です.導入したmoduleが存在しないと作成されます.これは、これらのmoduleのファイルをLABjsのようなツールで並行してロードすることができるという意味です.
広く開拓する
松の広がりは素晴らしいですが、あなたのmoduleには限界があります.最も重要な点は、moduleの属性を安全に書き換えることができません.初期化時には他のファイルのmodule属性も使えません.ハード展開には一定のロード順序が含まれていますが、書き換えをサポートしている例があります.
var MODULE = (function (my) {
    var old_moduleMethod = my.moduleMethod;
 
    my.moduleMethod = function () {
        // method override, has access to old through old_moduleMethod...
    };
 
    return my;
}(MODULE));
ここではMODLE.moduleMethodを書き直しました.必要に応じて原始的な方法に対する引用を残しました.
コピーと継承
var MODULE_TWO = (function (old) {
    var my = {},
        key;
 
    for (key in old) {
        if (old.hasOwnProperty(key)) {
            my[key] = old[key];
        }
    }
 
    var super_moduleMethod = old.moduleMethod;
    my.moduleMethod = function () {
        // override method on the clone, access to super through super_moduleMethod
    };
 
    return my;
}(MODULE));
このモードは最も柔軟ではない選択かもしれない.いくつかの優雅な合併を支持していますが、その代償は器用さを犠牲にしています.私たちが書いたコードの中では、これらのタイプは対象または関数の属性はコピーされません.一つのオブジェクトの二つの参照の形でのみ存在します.一つの変化、もう一つの変化.対象にとって[g 5]
 ,再帰的なクローン操作によって解決できますが、関数についてはeval以外に方法がありません.しかし、私は完全性のためにそれを含んでいます.
ファイル間のプライベート状態
一つのmoduleを複数のファイルに分けることには大きな限界があります.各ファイルは自分のプライベート状態を維持しています.他のファイルのプライベート状態を取得する方法がありません.これは解決できます.以下のこの緩い広がりの例は、異なる文書の中で私有状態を維持することができます.
var MODULE = (function (my) {
    var _private = my._private = my._private || {},
        _seal = my._seal = my._seal || function () {
            delete my._private;
            delete my._seal;
            delete my._unseal;
        },
        _unseal = my._unseal = my._unseal || function () {
            my._private = _private;
            my._seal = _seal;
            my._unseal = _unseal;
        };
 
    // permanent access to _private, _seal, and _unseal
 
    return my;
}(MODULE || {}));
各ファイルはそのプライベート変数_とすることができます.prvate設定属性は、他のファイルをすぐに呼び出すことができます.moduleのロードが完了すると、プログラムはMODULE.uを呼び出します.seal、外部に内部に接触することができないようにします.   _.prvateもし後にmoduleを再度開拓するならば、ある属性は変えます.新しいファイルを読み込む前に、どのファイルも呼び出しできます.unsea()は、コード実行後に_を呼び出します.seal
このパターンは今日の仕事で思い付きました.他のところで見たことがありません.しかし、これはとても有用なモデルだと思います.単独で書く価値があります.
Sub-modules
最後の高級モードは実は一番簡単で、子moduleを作る例がたくさんあります.
MODULE.sub = (function () {
    var my = {};
    // ...
 
    return my;
}());
これは簡単かもしれませんが、これは書かれる価値があると思います.サブmoduleは一般的なmoduleのすべての優れた特性を持っています.
締め括りをつける
ほとんどの上位モードは互いに結合してより有用な新しいモードを作成することができる.どうしても複雑なアプリケーションを設計する方法を提案してくれれば、松の開拓、私有状態、和子moduleを結合します.
ここでは性能については言及していませんが、moduleモードは性能向上に有利だと言えます.コードの量を減らすことができます.コードの読み込みが速くなります.松の広がりは並行ローディングを可能にしており、これと同様にロード速度が向上します.初期化の時間は他の方法よりも長いかもしれないが、これは多くの時間を費やす価値がある.グローバル変数が正しく導入されている限り、運転時には問題なく、サブモジュールでは変数への参照チェーンが短くなり、速度が上がる可能性があります.
最後に、これは身長module自身のダイナミックローディングの例です.(存在しないならば作成します.)プロフィールのために内部の状態を考えていませんが、それを考えても簡単です.このモードは、サブmoduleや他のすべてのものを含めて、複雑なマルチレベルのコードを並列にロードすることができます.
var UTIL = (function (parent, $) {
    var my = parent.ajax = parent.ajax || {};
 
    my.get = function (url, params, callback) {
        // ok, so I'm cheating a bit 
        return $.getJSON(url, params, callback);
    };
 
    // etc...
 
    return parent;
}(UTIL || {}, jQuery));
これらの内容が役に立ちますように、下のメッセージであなたの考えを共有してください.少年達、努力して、もっと良いのを書き出して、更にモジュール化のJavaScript.