JavaScript 设计模式:模块模式和揭示模块模式的区别? [英] JavaScript design pattern: difference between module pattern and revealing module pattern?

查看:27
本文介绍了JavaScript 设计模式:模块模式和揭示模块模式的区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近正在阅读学习 JavaScript 设计模式这本书.我不明白的是模块模式和揭示模块模式之间的区别.我觉得他们是同一个东西.谁能举个例子?

I'm reading the book Learning JavaScript Design Patterns recently. What I don't get is the difference between module pattern and revealing module pattern. I feel they are the same thing. Anyone can give an example?

推荐答案

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

There are at least three different ways to implement the Module Pattern, but the Revealing Module Pattern is the only Module Pattern descendant that has an official name.

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

The Module Pattern must satisfy the following:

  • 私人成员住在封闭区.
  • 公共成员在返回对象中公开.

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

But there's a lot of ambiguity in this definition. By resolving the ambiguity differently, you get variants of the Module Pattern.

揭示模块模式是最著名和最受欢迎的模块模式变体.与其他替代方案相比,它具有许多优点,例如

The Revealing Module Pattern is the most famous and most popular of the Module Pattern variants. It has a number of advantages over the other alternatives, such as

  • 重命名公共函数而不更改函数体.
  • 只需修改一行即可将成员从公共更改为私有,反之亦然,而无需更改函数主体.

RMP 满足原始条件之外的三个附加条件:

The RMP satisfies three additional conditions in addition to those in the original:

  • 所有成员,无论是公共成员还是私有成员,都在闭包中定义.
  • 返回对象是一个没有函数定义的对象字面量.所有右边的表达式都是闭包变量
  • 所有引用都是通过闭包变量,而不是返回对象.

下面的例子展示了它是如何使用的

The following example shows how it's used

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

如果您想将 namesayHello 设为私有,您只需要在返回对象中注释掉相应的行即可.

If you wanted to make name and sayHello private, you just need to comment out the appropriate lines in the return object.

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 不同的是,这个变种没有性感的官方名称.

The Module Pattern with Object Literal

This is probably the oldest variant of the Module Pattern. Unlike RMP, there's no sexy official name for this variant.

它满足以下条件,除了原来的:

It satisfies the following conditions, in addition to the original:

  • 私有成员在闭包中定义.
  • 公共成员在返回对象字面量中定义.
  • 尽可能通过this引用公共成员.
  • Private members are defined in the closure.
  • Public members are defined in the return object literal.
  • References to public members are via this, whenever possible.

在下面的示例中,您可以看到与 RMP 相比,函数定义实际上是在返回对象字面量中,对成员的引用由 this 限定.

In the following example, you can see how, in contrast to RMP, the function definitions are actually in the return object literal, and references to members are qualified by this.

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

请注意,与 RMP 不同的是,为了使 namesayHello 成为私有,指向 namesayHello在各种函数体定义中也必须改变.

Note that unlike RMP, in order to make name and sayHello private, the references pointing to name and sayHello in the various function body definitions also have to be changed.

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

带有返回对象存根的模块模式

这个变种也没有正式名称.

The Module Pattern with Return Object Stub

This variant also has no official name.

它满足以下条件,除了原来的:

It satisfies the following conditions, in addition to the original:

  • 在开头定义了一个空的返回对象存根.
  • 私有成员在闭包中定义.
  • 公共成员被定义为存根的成员
  • 通过存根对象引用公共成员

使用我们的旧示例,您可以看到公共成员直接添加到存根对象中.

Using our old example, you can see that public members are directly added to the stub object.

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

如果您想像以前一样将 namesayHello 设为私有,则必须更改对现在私有成员的引用.

If you want to make name and sayHello private as before, the references to the now-private members have to be changed.

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 在他关于 揭示模块模式,

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

A disadvantage of this pattern is that if a private function refers to a public function, that public function can't be overridden if a patch is necessary. This is because the private function will continue to refer to the private implementation and the pattern doesn't apply to public members, only to functions.

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

Public object members which refer to private variables are also subject to the no-patch rule notes above.

因此,使用揭示模块模式创建的模块可能比使用原始模块模式创建的模块更脆弱,因此在使用过程中应小心.

As a result of this, modules created with the Revealing Module pattern may be more fragile than those created with the original Module pattern, so care should be taken during usage.

我在一些其他帖子.

这篇关于JavaScript 设计模式:模块模式和揭示模块模式的区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆