1

私はjavascriptデザインパターンの本を読んでいて、「コマンドパターン」を読んでいるときに以下のコードに出くわしました。私は、このコードがすぐに呼び出される無名関数にラップされている理由を理解しようとしています。特に、クロージャーするプライベート変数が他にないためです。これは、CarManager をオブジェクト リテラルとして宣言することとどう違うのでしょうか?

(function(){

  var CarManager = {

    // request information
    requestInfo: function( model, id ){
      return 'The information for ' + model + ' with ID ' + id + ' is foobar';
    },

    // purchase the car
    buyVehicle: function( model, id ){
      return 'You have successfully purchased Item ' + id + ', a ' + model;
    },

    // arrange a viewing
    arrangeViewing: function( model, id ){
      return 'You have successfully booked a viewing of ' + model + ' ( ' + id + ' ) ';
    }

  };

})();
4

3 に答える 3

2

例は少し中途半端です。

目標は、パブリック インターフェイスを提供できるようにすることです。その IIFE 内に、インターフェースに必要なすべての部品をまとめます。

return ステートメントを介して戻す必要はありません。

たとえば、jQuery は同じ方法で構築されています。return ステートメントの代わりに:

var jQuery = (function () { return magic; }());

次のように、関数内からwindowjQuery(および) プロパティを手動で設定します。$

(function () { window["jQuery"] = magic; }());

さらに、実際に起こっていることは、まだ少し異なります。windowオブジェクトをIIFEのwindowパラメータに渡しています。である必要はありませんwindow。理論的には、拡張している以前に定義されたオブジェクトである可能性があります。

var myApp = {};
(function (window, document) { window["jQuery"] = public_interface; }(myApp, document));
myApp.jQuery("...");

jQuery に似たライブラリを構築する場合、同様のことができます。通常、大規模なライブラリ/アプリケーションに名前を付ける場合 (良い考えです)、内部で名前を短くして、作業を楽にすることができます。

それ以外の:

var NAMESPACED_AWESOME_APP_OF_DOOM = {}; NAMESPACED_AWESOME_APP_OF_DOOM.module1 = {};

次のようなことができます:

(function (namespace) {

    var ns = {};
    window[namespace] = ns;

    ns.module1 = {};
    ns.module2 = {};
    ns.service1 = function () {};

}("NAMESPACED_AWESOME_APP_OF_DOOM"));

その後、すべての内部設定を内部で行うことができ、設定が完了したら、グローバル スコープでアプリケーションを名前で参照できます。

他の場合では、このようにクロージャーを使用してコードのサンドボックスを作成し、メディエーターを使用してコンポーネント間でメッセージをやり取りすることができます。Nicholas Zakas は、これについていくつかの良い話をしています。

そして最後に、プログラムの残りの部分とは 100% 関係のない作業を完了させたい場合がありますが、それでも完了させる必要があります (互換性チェックを実行して結果を DOM 要素に結び付けるなど)。 Modernizr... ...そこに必要な Cookie を設定したり、分析ソフトウェアへの呼び出しを開始したり... ...など)。

于 2012-09-16T02:37:08.550 に答える
0

この特定の例では、匿名関数は、CarManager が他の場所からアクセスできないようにする、つまりグローバル スコープに入らないようにするためだけに機能します。

また、このコード インスタンスに固有のものであり、まったく無意味です。CarManager は他のコードでは使用できません。

コメントで提供したリンクを見ると、http://addyosmani.com/resources/essentialjsdesignpatterns/book/#commandpatternjavascript

私が知る限り、CarManager.execute ビットに加えて、文書化されているコードのセクション全体が完全に機能しなくなります。CarManager.execute = ... を匿名関数の外で定義しようとすると、CarManager が存在しないため失敗します。

于 2012-09-16T02:13:28.203 に答える
0

私はOPです。上記の議論に基づいて、著者が表現したいことを解釈しようとした後、次のコードが著者が表現したかった可能性があるという結論に達しました。少なくとも私にとっては、これは理にかなっているようです。

(function(){
    var CarManager = {
        requestInfo: function(model, id){
            /* blah blah */
        },
        buyVehicle: function(model, id){
            /* blah blah */
        },
        arrangeViewing: function( model, id ){
            /* blah blah */
        }
    };

    CarManager.execute = function(name){
        return CarManager[name] && CarManager[name].apply(CarManager, Array.prototype.slice(arguments, 1));
    }

    return CarManager;
}());

基本的に、無名関数の実行が CarManager オブジェクト リテラルを返す部分を追加しました。また、戻る前に execute メソッドを配置しました (ただし、コードの可読性以外に、元の CarManager オブジェクトの外にある必要がある理由はよくわかりません)。どう思いますか?

(ちなみに、本のセクションの Web バージョンはこちら: http://addyosmani.com/resources/essentialjsdesignpatterns/book/#commandpatternjavascript )

于 2012-09-16T02:56:07.760 に答える