私は 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番目のバリエーションでは呼び出されるたびにこの一時変数が作成されることです。
これが使用される理由についての最良の推測は、barのインスタンスの数を制限し(1つのみ)、メモリ管理のオーバーヘッドを節約することです。
私の質問:
あなたの仮定はほぼ正しいです。最初にそれらを確認しましょう。
- 自己実行機能の戻り値を割り当てます
これは 即時呼び出し関数式 または [〜#〜] iife [〜#〜] と呼ばれます
- この関数内でローカル変数を定義します
これは、private
キーワードまたはその他の機能を提供しないため、JavaScriptでプライベートオブジェクトフィールドを持つ方法です。
- ローカル変数を使用するロジックを含む実際の関数を返します。
繰り返しになりますが、重要な点は、このローカル変数はprivateです。
このパターンの名前はありますか?
知っている限り、このパターンを呼び出すことができます モジュールパターン 。引用:
Moduleパターンは、クロージャーを使用して「プライバシー」、状態、および組織をカプセル化します。パブリックとプライベートのメソッドと変数の混在をラップする方法を提供し、ピースがグローバルスコープに漏れたり、誤って別の開発者のインターフェイスと衝突したりするのを防ぎます。このパターンでは、パブリックAPIのみが返され、クロージャー内の他のすべてをプライベートに保ちます。
これらの2つの例を比較すると、最初の1つが使用される理由についての最良の推測は次のとおりです。
しかし、毎回Vanillaオブジェクトのみが必要な場合、このパターンはおそらく値を追加しません。
オブジェクトの初期化コストを制限し、さらにすべての関数呼び出しでsameオブジェクトを使用するようにします。これにより、たとえば、将来の呼び出しで使用するために状態をオブジェクトに保存できます。
メモリ使用量を制限することは可能ですが、通常はGCが未使用のオブジェクトを収集するため、このパターンはあまり役に立ちません。
このパターンは、特定の形式の closure です。
このパターンの名前が正しいかどうかはわかりませんが、これはモジュールのように見えます。また、使用される理由は、カプセル化と状態の維持の両方のためです。
クロージャー(関数内の関数によって識別される)は、内部関数が外部関数内の変数にアクセスできるようにします。
あなたが与えた例では、foo
がクロージャ内で生き続け、内部関数foo()
への複数の呼び出しが同じ上で動作することを意味する外部関数を実行することにより、内部関数が返されます(そしてtmpObject
に割り当てられます) tmpObject
のインスタンス。
コードとThree.jsコードの主な違いは、Three.jsコードでは変数tmpObject
が1回だけ初期化され、返された関数の呼び出しごとに共有されることです。
これは、Cのような言語でstatic
変数が使用されるのと同様に、呼び出し間で状態を保持するのに役立ちます。
tmpObject
は、内部関数からのみ見えるプライベート変数です。
メモリ使用量を変更しますが、メモリを節約するようには設計されていません。
すべてのメソッドと変数が明示的に公開されるまでプライベートに保たれるようにする、明らかにするモジュールパターンの概念に拡張することで、この興味深いスレッドに貢献したいと思います。
後者の場合、追加メソッドはCalculator.add()として呼び出されます。