65

最近、 Learning JavaScript Design Patternsという本を読んでいます。私が得られないのは、モジュールパターンと明らかにモジュールパターンの違いです。それらは同じものだと感じています。誰でも例を挙げることができますか?

4

3 に答える 3

121

モジュール パターンを実装するには、少なくとも 3 つの異なる方法がありますが、公開モジュール パターンは、正式な名前を持つ唯一のモジュール パターンの子孫です。

基本モジュール パターン

モジュール パターンは、次の条件を満たす必要があります。

  • プライベートメンバーは閉鎖に住んでいます。
  • パブリック メンバーは、戻りオブジェクトで公開されます。

しかし、この定義には多くのあいまいさがあります。あいまいさを別の方法で解決することにより、モジュール パターンのバリアントを取得します。

Revealing モジュール パターン

Revealing Module Pattern は、Module Pattern バリアントの中で最も有名で最も人気のあるものです。他の代替手段に比べて、次のような多くの利点があります。

  • 関数本体を変更せずにパブリック関数の名前を変更します。
  • 関数本体を変更せずに、1 行を変更するだけでメンバーを public から private に、またはその逆に変更します。

RMP は、元の条件に加えて、次の 3 つの追加条件を満たします。

  • public か private かに関係なく、すべてのメンバーはクロージャで定義されます。
  • 返されるオブジェクトは、関数定義のないオブジェクト リテラルです。右辺の式はすべてクロージャ変数です
  • すべての参照は、戻りオブジェクトではなく、クロージャー変数を介して行われます。

次の例は、その使用方法を示しています

var welcomeModule = (function(){
  var name = "John";
  var hello = function(){ console.log("Hello, " + name + "!");}
  var welcome = function() { console.log( hello() + " Welcome to StackOverflow!");}
  return {
    name: name,
    sayHello: hello,
    sayWelcome: welcome
  }
})();

makenamesayHelloprivate が必要な場合は、return オブジェクトの適切な行をコメント アウトするだけです。

var welcomeModule = (function(){
  var name = "John";
  var hello = function(){ console.log("Hello, " + name + "!");}
  var welcome = function() { console.log( hello() + " Welcome to StackOverflow!");}
  return {
    //name: name,
    //sayHello: hello,
    sayWelcome: welcome
  }
})();

オブジェクト リテラルを使用したモジュール パターン

これはおそらくモジュール パターンの最も古い変種です。RMP とは異なり、この亜種にはセクシーな公式名はありません。

オリジナルに加えて、次の条件を満たしています。

  • プライベート メンバーはクロージャで定義されます。
  • パブリック メンバーは、戻りオブジェクト リテラルで定義されます。
  • パブリック メンバーへの参照はthis、可能な限り 経由で行います。

次の例では、RMP とは対照的に、関数定義が実際には戻りオブジェクト リテラルにあり、メンバーへの参照がthis.

var welcomeModule = (function(){
  return {
    name: "John",
    sayHello: function(){ console.log("Hello, " + this.name + "!");}
    sayWelcome: function() { console.log( this.hello() + " Welcome to StackOverflow!");}
  }
})();

RMP とは異なり、makenameおよびprivate を行うには、さまざまな関数本体定義内のおよびをsayHello指す参照も変更する必要があることに注意してください。namesayHello

var welcomeModule = (function(){
  var name = "John";
  var sayHello = function(){ console.log("Hello, " + name + "!");};
  return {
    //name: "John",
    //sayHello: function(){ console.log("Hello, " + this.name + "!");}
    sayWelcome: function() { console.log( hello() + " Welcome to StackOverflow!");}
  }
})();

リターン オブジェクト スタブを使用したモジュール パターン

この亜種にも正式な名前はありません。

オリジナルに加えて、次の条件を満たしています。

  • 空の戻りオブジェクト スタブが最初に定義されます。
  • プライベート メンバーはクロージャで定義されます。
  • パブリック メンバーは、スタブのメンバーとして定義されます
  • パブリック メンバーへの参照は、スタブ オブジェクトを介して行われます

古い例を使用すると、パブリック メンバーがスタブ オブジェクトに直接追加されていることがわかります。

var welcomeModule = (function(){
  var stub = {};
  stub.name = "John";
  stub.sayHello = function(){ console.log("Hello, " + stub.name + "!");}
  stub.sayWelcome = function() { console.log( stub.hello() + " Welcome to StackOverflow!");}
  return stub;
})();

name以前のように作成して非公開にしたい場合はsayHello、非公開メンバーへの参照を変更する必要があります。

var welcomeModule = (function(){
  var stub = {};
  var name = "John";
  var sayHello = function(){ console.log("Hello, " + name + "!");}
  
  stub.sayWelcome = function() { console.log( hello() + " Welcome to StackOverflow!");}
  return stub;
})();

概要

Revealing Module パターンと Module パターンの他のバリアントとの違いは、主にパブリック メンバーの参照方法にあります。その結果、RMP は使用と変更がはるかに簡単であり、これが人気の理由です。ただし、これらの利点には多大な代償が伴います (私の意見では)。Addy Osmani はモジュール パターンの公開に関する投稿で言及しています。

このパターンの欠点は、プライベート関数がパブリック関数を参照する場合、パッチが必要な場合にそのパブリック関数をオーバーライドできないことです。これは、プライベート関数が引き続きプライベート実装を参照し、パターンがパブリック メンバーには適用されず、関数にのみ適用されるためです。

プライベート変数を参照するパブリック オブジェクト メンバーも、上記のノーパッチ ルール ノートの対象となります。

この結果、Revealing Module パターンで作成されたモジュールは、元の Module パターンで作成されたモジュールよりも壊れやすい可能性があるため、使用中は注意が必要です。

これについては、他のいくつかの 投稿で話しました。

于 2014-04-07T16:55:44.127 に答える