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
和说你好私人,在各种函数体定义中指向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; })();
如果你想和以前一样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中提到过这个问题。