JavaScriptdevise模式:模块模式与显示模块模式的区别?

我正在阅读最近学习JavaScriptdevise模式的书。 我没有得到的是模块模式和显示模块模式之间的区别。 我觉得他们是一回事。 任何人都可以举个例子吗?

至less有三种不同的方式来实现模块模式,但是揭示模块模式是具有正式名称的唯一模块模式后代。

基本模块模式

模块模式必须满足以下条件:

  • 私人成员住在closures。
  • 公共成员暴露在返回对象中。

但是这个定义有很多不明确的地方。 通过以不同的方式解决歧义,您可以获得模块模式的变体。

揭示模块模式

揭示模块模式是最着名和最stream行的模块模式变种。 与其他select相比,它具有许多优点,例如

  • 重命名公共职能而不更改function主体。
  • 通过修改一行代码将成员从公共私有变为私有,或者反之亦然,无需更改函数体。

除了原始版本外,RMP还满足三个附加条件:

  • 所有成员,无论是公共的还是私人的,都在封闭中定义。
  • 返回对象是没有函数定义的对象文字。 所有右侧的expression式都是闭包variables
  • 所有引用都是通过闭包variables,而不是返回对象。

以下示例显示了如何使用它

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 } })(); 

如果你想要说出你的name并且说你好,你只需要在返回对象中注释掉相应的行。

 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!");} } })(); 

请注意,unlke RMP,为了使name和说你好私人,在各种函数体定义中指向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; })(); 

如果你想和以前一样sayHello私人name ,那么现在私人会员的引用必须改变。

 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; })(); 

概要

“揭示模块模式”与“模块模式”的其他变体之间的区别主要在于如何引用公共成员。 因此,RMP更易于使用和修改,这也是其受欢迎的原因。 然而,这些好处的成本很高(在我看来),Addy Osmani在揭示模块模式中的暗示,

这种模式的一个缺点是,如果一个私有函数引用一个公共函数,那么如果补丁是必要的,则该公共函数不能被覆盖。 这是因为私有函数将继续引用私有实现,而模式不适用于公共成员,而只适用于函数。

引用私有variables的公共对象成员也受上述无补丁规则注释的约束。

因此,使用“展示模块”模式创build的模块可能比使用原始模块模式创build的模块更脆弱,因此在使用过程中应该小心。

而我在其他一些post中提到过这个问题。