web-dev-qa-db-ja.com

このJavaScriptパターンは何と呼ばれ、なぜ使用されるのですか?

私は THREE.js を勉強していますが、関数が次のように定義されているパターンに気付きました:

var foo = ( function () {
    var bar = new Bar();

    return function ( ) {
        //actual logic using bar from above.
        //return result;
    };
}());

(例はraycastメソッド here を参照してください)。

このようなメソッドのnormalバリエーションは次のようになります。

var foo = function () {
    var bar = new Bar();

    //actual logic.
    //return result;
};

最初のバージョンをnormalバリエーションと比較すると、最初のバージョンは次の点で異なるようです:

  1. 自己実行機能の結果を割り当てます。
  2. この関数内でローカル変数を定義します。
  3. ローカル変数を使用するロジックを含むactual関数を返します。

主な違いは、最初のバリエーションでは初期化時にバーが1回しか割り当てられず、2番目のバリエーションでは呼び出されるたびにこの一時変数が作成されることです。

これが使用される理由についての最良の推測は、barのインスタンスの数を制限し(1つのみ)、メモリ管理のオーバーヘッドを節約することです。

私の質問:

  1. この仮定は正しいですか?
  2. このパターンの名前はありますか?
  3. なぜこれが使用されるのですか?
100
Patrick Klug

あなたの仮定はほぼ正しいです。最初にそれらを確認しましょう。

  1. 自己実行機能の戻り値を割り当てます

これは 即時呼び出し関数式 または [〜#〜] iife [〜#〜] と呼ばれます

  1. この関数内でローカル変数を定義します

これは、privateキーワードまたはその他の機能を提供しないため、JavaScriptでプライベートオブジェクトフィールドを持つ方法です。

  1. ローカル変数を使用するロジックを含む実際の関数を返します。

繰り返しになりますが、重要な点は、このローカル変数はprivateです。

このパターンの名前はありますか?

知っている限り、このパターンを呼び出すことができます モジュールパターン 。引用:

Moduleパターンは、クロージャーを使用して「プライバシー」、状態、および組織をカプセル化します。パブリックとプライベートのメソッドと変数の混在をラップする方法を提供し、ピースがグローバルスコープに漏れたり、誤って別の開発者のインターフェイスと衝突したりするのを防ぎます。このパターンでは、パブリックAPIのみが返され、クロージャー内の他のすべてをプライベートに保ちます。

これらの2つの例を比較すると、最初の1つが使用される理由についての最良の推測は次のとおりです。

  1. シングルトン設計パターンを実装しています。
  2. 最初の例を使用して、特定のタイプのオブジェクトを作成する方法を制御できます。この点との密接な一致は、「有効なJava」で説明されているように、 静的なファクトリメソッド になります。
  3. 毎回同じオブジェクト状態が必要な場合は、 効率的 です。

しかし、毎回Vanillaオブジェクトのみが必要な場合、このパターンはおそらく値を追加しません。

100

オブジェクトの初期化コストを制限し、さらにすべての関数呼び出しでsameオブジェクトを使用するようにします。これにより、たとえば、将来の呼び出しで使用するために状態をオブジェクトに保存できます。

メモリ使用量を制限することは可能ですが、通常はGCが未使用のオブジェクトを収集するため、このパターンはあまり役に立ちません。

このパターンは、特定の形式の closure です。

11
Fengyang Wang

このパターンの名前が正しいかどうかはわかりませんが、これはモジュールのように見えます。また、使用される理由は、カプセル化と状態の維持の両方のためです。

クロージャー(関数内の関数によって識別される)は、内部関数が外部関数内の変数にアクセスできるようにします。

あなたが与えた例では、fooがクロージャ内で生き続け、内部関数foo()への複数の呼び出しが同じ上で動作することを意味する外部関数を実行することにより、内部関数が返されます(そしてtmpObjectに割り当てられます) tmpObjectのインスタンス。

8
itsmejodie

コードとThree.jsコードの主な違いは、Three.jsコードでは変数tmpObjectが1回だけ初期化され、返された関数の呼び出しごとに共有されることです。

これは、Cのような言語でstatic変数が使用されるのと同様に、呼び出し間で状態を保持するのに役立ちます。

tmpObjectは、内部関数からのみ見えるプライベート変数です。

メモリ使用量を変更しますが、メモリを節約するようには設計されていません。

5
mcfedr

すべてのメソッドと変数が明示的に公開されるまでプライベートに保たれるようにする、明らかにするモジュールパターンの概念に拡張することで、この興味深いスレッドに貢献したいと思います。

enter image description here

後者の場合、追加メソッドはCalculator.add()として呼び出されます。

4
carlodurso