我最近正在阅读学习JavaScript设计模式这本书。我不能得到的是模块模式和揭示模块模式之间的区别。我觉得他们是一回事。任何人都可以举个例子吗?
答案 0 :(得分:100)
实现模块模式至少有三种不同的方法,但Revealing Module Pattern是唯一具有正式名称的模块模式后代。
模块模式必须满足以下条件:
但是这个定义中存在很多含糊之处。通过不同地解决歧义,您可以获得模块模式的变体。
Revealing Module Pattern是最着名和最受欢迎的Module Pattern变体。与其他替代方案相比,它具有许多优势,例如
除了原始版本之外,RMP还满足三个附加条件:
以下示例显示了它的使用方式
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
和sayHello
设为私有,则只需要在返回对象中注释掉相应的行。
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!");}
}
})();
请注意,为了使name
和sayHello
为私有,取消RMP,在各种函数体定义中指向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 Pattern与Module Pattern的其他变体之间的差异主要在于如何引用公共成员。因此,RMP更易于使用和修改,这也是其受欢迎程度的原因。然而,这些优势成本很高(在我看来),Addy Osmani在Revealing Module Pattern的帖子中暗示,
这种模式的一个缺点是,如果私有函数引用公共函数,如果需要补丁,则不能覆盖该公共函数。这是因为私有函数将继续引用私有实现,并且该模式不适用于公共成员,仅适用于函数。
引用私有变量的公共对象成员也受上面的无补丁规则说明的约束。
因此,使用Revealing Module模式创建的模块可能比使用原始模块模式创建的模块更脆弱,因此在使用过程中应该小心。
答案 1 :(得分:1)
简短的回答, 在模块模式中,我们在返回对象中定义函数。
在Revealing Module模式中,我们在闭包区域中定义函数,并仅在返回对象中使用变量名。
这样做可以简化代码并具有很多其他优点
答案 2 :(得分:0)
尝试根据热门评论回答做一些事情。如果通过将 此 传递给它来调用私有函数可能会更安全,因此私有函数可以使用 this 来引用公共函数strong>变量。
我用以下代码创建了一个揭示模块模式。
var HTMLChanger = (function () {
var privateFunc = function () {
this.sayHello();
}
var hello = function () {
console.log('say Hello');
}
var callPrivate = function () {
privateFunc.call(this);
}
return {
sayHello: hello,
callPrivate: callPrivate
};
})();
HTMLChanger.callPrivate();
//say Hello
HTMLChanger.sayHello = function() { console.log('say Hi!') };
HTMLChanger.callPrivate();
//say Hi!
如您所见,我们可以覆盖公共成员。