モジュラープログラミングは、非常に一般的なJavaScriptプログラミングパターンです。通常、コードを理解しやすくすることができますが、よく知られていない多くの優れたプラクティスがあります。
ベース
Eric Miraglia(Yuiの開発者)が3年前にモジュールパターンを説明するブログを最初に公開したため、最初にいくつかのモジュールパターンを簡単に概説しましょう。これらのモジュラーモードにすでに精通している場合は、このセクションを直接スキップして、「Advanced Mode」から読み始めることができます。
匿名の閉鎖
これは、すべてを可能にする基本構造であり、JavaScriptの最良の機能でもあります。匿名の関数を作成し、すぐに実行します。すべてのコードはこの関数内で実行され、民営化を提供する閉鎖の中で生きます。これにより、これらの閉鎖の変数がアプリケーションの寿命全体を実行できるようになります。
コードコピーは次のとおりです。
(関数 () {
// ...すべてのVARSと機能はこの範囲にのみあります
//すべてのグローバルへのアクセスを維持しています
}());
このペアの最も外側のブラケットに注意してください匿名関数をラッピングします。 JavaScriptの言語特性のため、これはブラケットに必要です。 JSのキーワード関数から始まるステートメントは、常に関数宣言と見なされます。このコードをブラケットに包み、これが関数式であることを通訳者に知らせます。
グローバル変数インポート
JavaScriptには、暗黙的なグローバル変数と呼ばれる機能があります。変数名がどこで使用されていても、通訳者はスコープチェーンに従って変数のvar宣言ステートメントを逆に見つけます。 VAR宣言の声明が見つからない場合、この変数はグローバル変数と見なされます。この変数が割り当てステートメントで使用され、変数が存在しない場合、グローバル変数が作成されます。これは、匿名の閉鎖で簡単に使用またはグローバル変数を作成できることを意味します。残念ながら、これにより、コードの維持が非常に難しくなります。人々の直感的な感情のために、これらの変数がグローバルであることを一目で伝えることは不可能であるためです。
幸いなことに、私たちの匿名関数は簡単な回避策を提供します。グローバル変数をパラメーターとして匿名関数に渡すだけで、暗黙のグローバル変数よりも明確かつ高速なコードを取得できます。これが例です:
コードコピーは次のとおりです。
(function($、yahoo){
//このコードでGlobals JQuery($)とYahooにアクセスできるようになりました
}(jquery、yahoo));
モジュールエクスポート
グローバル変数を使用するだけでなく、繰り返し使用するためにそれらを宣言したい場合もあります。匿名関数の返品値を通じて、それらを派生させることでこれを簡単に行うことができます。そうすることで、基本的なモジュラーモデルが完了し、以下が完全な例になります。
コードコピーは次のとおりです。
var module =(function(){
var my = {}、
privateVariable = 1;
関数privatemethod(){
// ...
}
my.moduleProperty = 1;
my.modulemethod = function(){
// ...
};
私を返してください;
}());
モジュールと呼ばれるグローバルモジュールを宣言したことに注意してください。これには、Module.ModuleMethodと呼ばれるメソッドとModule.ModulePropertyと呼ばれる変数があります。さらに、匿名の関数閉鎖を利用するプライベートビルトイン状態を維持しています。同時に、必要なグローバル変数を簡単にインポートし、以前に学んだようにこのモジュラーパターンを使用できます。
高度なモード
上記のセクションで説明する基礎は多くの状況に対処するのに十分であり、このモジュールモデルをさらに開発して、より強力でスケーラブルな構造を作成できます。モジュールモジュールから始めて、これらの高度なモードを1つずつ紹介しましょう。
ズームモード
モジュール全体は、1つのファイルでモジュラーモードの制限である必要があります。大規模なプロジェクトに関与している人は誰でも、JSで複数のファイルを分割することの価値を理解します。幸いなことに、モジュールを増幅するための優れた実装があります。まず、モジュールをインポートし、プロパティを追加し、最後にエクスポートします。これが例です - 元のモジュールからズームインしてください:
コードコピーは次のとおりです。
var module =(function(my){
my.anothermethod = function(){
//追加方法...
};
私を返してください;
}(モジュール));
ここでは必要ではありませんが、一貫性を確保するためにVARキーワードを使用します。このコードが実行された後、モジュールにはすでにモジュールと呼ばれる新しいパブリックメソッドがあります。AnotherMethod。この拡大されたファイルは、独自のプライベートビルトイン状態およびインポートされたオブジェクトも維持します。
ワイドズームモード
上記の例では、最初に初期化モジュールを実行し、次に変更するモジュールを実行する必要があります。もちろん、これは必ずしも必要ではない場合があります。 JavaScriptアプリケーションがパフォーマンスを改善するためにできる最良のことの1つは、スクリプトを非同期に実行することです。柔軟なマルチパートモジュールを作成し、ワイドズームモードを介して任意の順序でロードできるようにすることができます。各ファイルは、次の構造で編成する必要があります。
コードコピーは次のとおりです。
var module =(function(my){
//機能を追加...
私を返してください;
}(モジュール|| {}));
このパターンでは、VAR式が必要になります。モジュールが初期化されていない場合、このインポートステートメントはモジュールを作成することに注意してください。つまり、LABJSなどのツールを使用して、ブロックされずにすべてのモジュールファイルを並行してロードできることを意味します。
緊密な拡大モード
ワイドエンラージュモードは非常に優れていますが、モジュールにもいくつかの制限があります。最も重要なことは、モジュールのプロパティを安全に上書きすることができないことです。初期化時に他のファイルのプロパティを使用することはできません(ただし、実行時に使用できます)。緊密な拡大モードには、負荷付きシーケンスが含まれており、オーバーライドプロパティが可能になります。簡単な例を次に示します(元のモジュールのズーム):
コードコピーは次のとおりです。
var module =(function(my){
var old_modulemethod = my.modulemethod;
my.modulemethod = function(){
//メソッドオーバーライド、old_modulemethodから古いものにアクセスできます...
};
私を返してください;
}(モジュール));
上記の例では、module.modulemethodの実装をオーバーライドしますが、必要に応じて元の方法への参照を維持できます。
クローンと継承
コードコピーは次のとおりです。
var module_two =(function(old){
var my = {}、
鍵;
for(古いもののキー){
if(old.hasownproperty(key)){
私の[key] = old [key];
}
}
var super_modulemethod = old.modulemethod;
my.modulemethod = function(){
//クローンのオーバーライドメソッド、super_modulemethodを介してスーパーへのアクセス
};
私を返してください;
}(モジュール));
このモデルは、おそらく最も柔軟性のないオプションです。コードはきれいに見えますが、柔軟性が犠牲になります。上に書いたように、プロパティがオブジェクトまたは関数である場合、コピーされることはありませんが、オブジェクトまたは関数への2番目の参照になります。それらのいずれかを変更すると、他のものを同時に変更します(翻訳者の注意:単に1つだからです!)。これは、再帰的なクローニングプロセスによって解決できますが、関数のクローニングは解決できない場合があります。したがって、この記事ではこの方法でこの方法を伝えています。記事の完全性を考慮しています。
クロスファイルのプライベート変数
モジュールを複数のファイルに分割することには大きな制限があります。各ファイルは独自のプライベート変数を維持し、他のファイルのプライベート変数にアクセスできません。しかし、この問題は解決できます。ファイル間のプライベート変数を維持する広範囲のモジュールの例を次に示します。
コードコピーは次のとおりです。
var module =(function(my){
var _private = my._private = my._private || {}、
_seal = my._seal = my._seal ||関数 () {
my._privateを削除します。
my._sealを削除します。
my._unsealを削除します。
}、
_unseal = my._unseal = my._unseal ||関数 () {
my._private = _private;
my._seal = _seal;
my._unseal = _unseal;
};
// _private、_seal、_unsealへの永続的なアクセス
私を返してください;
}(モジュール|| {}));
すべてのファイルは、それぞれの_private変数にプロパティを設定でき、他のファイルからアクセスできることを理解しています。このモジュールがロードされると、アプリケーションはmodule._seal()を呼び出して、内部_privateへの外部呼び出しを防ぎます。このモジュールを再マグインする必要がある場合、任意のファイルの内部メソッドは、新しいファイルをロードする前に_unseal()を呼び出し、新しいファイルが実行された後に_seal()を再度呼び出すことができます。私は今職場でこのパターンを使用していますが、他の場所では見ていません。これは非常に便利なモデルであり、このモデル自体に関する記事を書く価値があると思います。
サブモジュール
私たちの最後の高度なモードは明らかに最も簡単です。サブモジュールの作成には多くの優れた例があります。それは通常のモジュールを作成するようなものです:
コードコピーは次のとおりです。
module.sub =(function(){
var my = {};
// ...
私を返してください;
}());
これは簡単に思えますが、ここで言及する価値があると思います。サブモジュールには、増幅モードや民営化状態など、一般的なモジュールのすべての高度な利点があります。
結論は
最も高度なモードを組み合わせて、より便利なモードを作成できます。複雑なアプリケーションを設計するためのモジュラーパターンを本当に推奨したい場合は、ワイド増幅モード、プライベート変数、およびサブモジュールを組み合わせることを選択します。
私はこれらのモードのパフォーマンスを検討していませんが、これをより簡単な考え方に変えたいです。モジュラーモードが優れたパフォーマンスを持っている場合、それを最小限に抑えて、このスクリプトファイルをより速くダウンロードすることができます。広い拡大モードを使用すると、単純な非ブロッキングパラレルダウンロードが可能になり、ダウンロードが高速化されます。初期化時間は他の方法よりもわずかに遅くなる可能性がありますが、長所と短所を比較検討した後は価値があります。グローバル変数のインポートが正確である限り、ランタイムパフォーマンスに影響を与えるはずであり、プライベート変数で参照チェーンを短縮することにより、サブモジュールのより速いランニング速度を達成することも可能です。
結論として、ここに子供モジュールが親モジュールに動的にロードする例を示します(親モジュールが存在しない場合に作成します)。簡単にするために、私はプライベート変数を削除しましたが、もちろんプライベート変数を追加するのは非常に簡単です。このプログラミングパターンにより、複雑な階層構造コードベース全体をサブモジュールを介して並行してロードできます。
コードコピーは次のとおりです。
var util =(function(parent、$){
var my = parent.ajax = parent.ajax || {};
my.get = function(url、params、callback){
// OK、だから私は少しだましている:)
$ .getjson(url、params、callback)を返します。
};
//など...
親を返します。
}(util || {}、jQuery));
この記事では、「JavaScriptモジュラープログラミング」の現在のベストプラクティスをまとめて、それを実践する方法について説明します。これは主要なチュートリアルではありませんが、JavaScriptの基本的な構文を少し理解することで理解できます。