最近、 Learning JavaScript Design Patternsという本を読んでいます。私が得られないのは、モジュールパターンと明らかにモジュールパターンの違いです。それらは同じものだと感じています。誰でも例を挙げることができますか?
3 に答える
モジュール パターンを実装するには、少なくとも 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
}
})();
makename
とsayHello
private が必要な場合は、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
指す参照も変更する必要があることに注意してください。name
sayHello
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 パターンで作成されたモジュールよりも壊れやすい可能性があるため、使用中は注意が必要です。