例のJavaScriptモジュールパターン[終了]


136

2つ(またはそれ以上)の異なるモジュールがどのように接続されて連携するかを示すアクセス可能な例が見つかりません。

それで、モジュールがどのように連携するかを説明する例を書く時間があるかどうか尋ねたいと思います。


これは過去4年間ですべて変更されましたが、熱心な節度のおかげで、この古くなった情報は永久に残ります。これはES6モジュールに関するMDNのページです。
bbsimonbb 2017

回答:


256

モジュラー設計パターンにアプローチするには、まずこれらの概念を理解する必要があります。

即座に呼び出される関数式(IIFE):

(function() {
      // Your code goes here 
}());

関数を使用するには2つの方法があります。1.関数宣言2.関数式。

ここでは関数式を使用しています。

名前空間とは何ですか?上記のコードに名前空間を追加すると、

var anoyn = (function() {
}());

JSの閉鎖とは何ですか?

つまり、変数スコープ/別の関数内で関数を宣言すると(JSでは別の関数内で関数を宣言できます!)、その関数スコープが常にカウントされます。つまり、外部関数の変数は常に読み取られます。同じ名前のグローバル変数(存在する場合)は読み取られません。これは、名前の競合を回避するモジュール設計パターンを使用する目的の1つでもあります。

var scope = "I am global";
function whatismyscope() {
    var scope = "I am just a local";
    function func() {return scope;}
    return func;
}
whatismyscope()()

ここで、上記の3つの概念を適用して、最初のモジュール設計パターンを定義します。

var modularpattern = (function() {
    // your module code goes here
    var sum = 0 ;

    return {
        add:function() {
            sum = sum + 1;
            return sum;
        },
        reset:function() {
            return sum = 0;    
        }  
    }   
}());
alert(modularpattern.add());    // alerts: 1
alert(modularpattern.add());    // alerts: 2
alert(modularpattern.reset());  // alerts: 0

上記のコードのjsfiddle。

目的は、変数のアクセシビリティを外部の世界から隠すことです。

お役に立てれば。幸運を。


iifeに名前を付けた方が良いでしょうか?意味上の目的とより良いスタックトレースのために?コードで何かを変更しますか?
Jeroen 2014年

2
最初の例(function() { /* Your code goes here */}());は実際にはIIFE(Immediately Invoking Function Expression)です。名前はないので、それをIIAFE(Immediately Invomous Anonymous Function Expression)と呼んでもかまいません。IIFEの詳細については、stackoverflow.com
エイドリアンは

なぜreturnステートメントが使用されたのですか?return {}を省略した場合、addおよびreset関数はパブリックになり、ローカル変数sumにアクセスできると思いますか?私は正しいですか?
Mou

2番目の例はオブジェクトのように見えますか、それとも正しくありませんか?
理由

4
これはOPの質問には対応していません。これはモジュールパターンの説明であり、OPが望むように複数のモジュールがどのように連携するかを示す例ではありません。
Erik Trautman、2015

39

私はこのテーマを入力している人なら誰でもAddy Osmaniの無料の本を読むことを勧めます:

「JavaScriptデザインパターンの学習」。

http://addyosmani.com/resources/essentialjsdesignpatterns/book/

この本は、私がより保守しやすいJavaScriptを書き始めたときに非常に役立ちました。彼のさまざまなモジュールパターンの実装を見てください。彼はそれらを非常によく説明しています。



1
これは、Stoyan Stefanov
JohnMerlinoに

4
ストヤンの本ははるかに包括的です。高レベルのパターンだけでなく、他のJSのベストプラクティスについても詳しく説明しています。
Code Novitiate 2014

1
"Learning JavaScript Design Patterns"のレビューamazon.com/product-reviews/1449331815
Adrien Be

3
Stoyan Stefanov amazon.com/product-reviews/0596806752による "JavaScript Patterns"のレビュー。注:「JavaScriptのデザインパターンを学習する」よりもはるかに優れているようです
Adrien Be

19

上記の答えをさらに拡張して、モジュールをアプリケーションにどのように組み合わせるかについて話したいと思いました。私はこれについてダグ・クロックフォードの本で読んだことがありますが、JavaScriptが初めてなので、まだ少し不思議でした。

私はc#のバックグラウンド出身なので、そこから役立つ用語をいくつか追加しました。

HTML

なんらかのトップレベルのhtmlファイルができます。これをプロジェクトファイルと考えると役立ちます。プロジェクトに追加するすべてのjavascriptファイルはこれに移動したいのですが、残念ながら、これに対するツールのサポートはありません(私はIDEAを使用しています)。

次のようなスクリプトタグを使用して、プロジェクトにファイルを追加する必要があります。

        <script type="text/javascript" src="app/native/MasterFile.js" /></script>
        <script type="text/javascript" src="app/native/SomeComponent.js" /></script>

タグを折りたたむと問題が発生するように見えます-xmlのように見えますが、実際にはもっとおかしなルールのあるものです!

名前空間ファイル

MasterFile.js

myAppNamespace = {};

それでおしまい。これは、残りのコードが存在する単一のグローバル変数を追加するためのものです。ネストされた名前空間をここで(または独自のファイルで)宣言することもできます。

モジュール

SomeComponent.js

myAppNamespace.messageCounter= (function(){

    var privateState = 0;

    var incrementCount = function () {
        privateState += 1;
    };

    return function (message) {
        incrementCount();
        //TODO something with the message! 
    }
})();

ここでは、アプリケーションの変数にメッセージカウンター関数を割り当てています。これは、すぐに実行される関数を返す関数です。

概念

SomeComponentの一番上の行を、何かを宣言している名前空間であると考えると役立つと思います。これに対する唯一の注意点は、すべての名前空間を他のファイルに最初に表示する必要があることです。これらは、アプリケーション変数をルートとする単なるオブジェクトです。

私は現時点でこれを使って小さな手順を実行しただけです(extjsアプリからいくつかの通常のjavascriptをリファクタリングしてテストできるようにしています)が、「これの泥沼を避けながら小さな機能単位を定義できるので、とてもいいようです」 '

このスタイルを使用して、関数のコレクションを持つオブジェクトを返す関数を返し、すぐには呼び出さないことで、コンストラクターを定義することもできます。


6

こちらのhttps://toddmotto.com/mastering-the-module-patternでは、完全に説明されたパターンを見つけることができます。モジュラーJavaScriptの2番目のことは、コードを複数のファイルに構成する方法です。多くの人々がAMDを使用するようにここであなたにアドバイスするかもしれませんが、経験から、多数のHTTPリクエストのためにページの応答が遅くなると私は言うことができます。解決策は、JavaScriptモジュール(ファイルごとに1つ)をCommonJS標準に従って1つのファイルにプリコンパイルすることです。こちらのサンプルをご覧くださいhttp://dsheiko.github.io/cjsc/


すべてのAMD実装は、単一ファイルへのプリコンパイルも提供します。
I-Lin Kuo

1
それは正しいですが、結果の最適化されたファイルにはローダーライブラリが必要です(r.js v2.1.14で再確認するだけです)。これは通常、かなり重いです。コードをコンパイルしたらすぐに、非同期で読み込まれた依存関係を解決する必要はありませんが、このライブラリは必要ありません。ただ考慮してください:モジュールをAMDにラップします。つまり、非同期です。ロードしてから、それらを1つのファイルにコンパイルします(個別にロードする必要はありません)が、ライブラリ全体をロードしてそれらに対処します(現在は冗長です)。それは私にとって最適な方法とは思えません。非同期にロードしないのに、なぜAMDなのか?
Dmitry Sheiko 2014

almond.jsはReq​​uireJSよりも完成したプロダクションコード用の軽量ローダーを提供しますが、比較的言えば、単一のhttpリクエストを作成しないことによるパフォーマンス上の利点は、ローダーコードをモジュールに追加するコストをはるかに上回るため、最適ではありませんが、はるかに小さなスケールで。私の意見では、この問題は回避すべきです-なぜブラウザーが同期していないときに同期性を仮定するのですか?私はRequireJSとCommonJSの両方を内蔵約束の履行を有するべきであるという意見で、実際だ。
I-林クオ

どちらの形式もCommonJS Modules / 2.0への有効なパスであり、同じスケーラビリティを提供します。私にとっては-CJS Modules / 1.1(私がCommonJSで意味していること)を処理する方がはるかに簡単で、コードはきれいに見えます。
ドミトリーシェイコ2014

AMDには次のようなメリットがあります。* JavaScriptファイルだけでなく、他のものもロードできます。*パスのエイリアス。まあ、CommonJSコンパイラはこれらを解決します。JavaScipt/ JSON以外の依存関係をデータとしてロードし、ビルド構成(エイリアスを含む)で提供できます。構築が必要な唯一の欠点。しかし、今日では誰もがとにかくCSSプリプロセッサ用のプロジェクトを構築しています。それは...兵卒/ガルプのための余分なタスクを追加する方法についてだけであるので
ドミトリーSheiko

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.