[英]How do I call a public function from within a private function in the JavaScript Module Pattern
How do I call a public function from within a private function in the JavaScript Module Pattern? 如何在JavaScript模块模式的私有函数中调用公共函数?
For example, in the following code, 例如,在以下代码中,
var myModule = (function() {
var private1 = function(){
// How to call public1() here?
// this.public1() won't work
}
return {
public1: function(){ /* do something */}
}
})();
This question has been asked twice before , with a different accepted answer for each. 这个问题之前曾被问过两次 ,但每个问题的答案都不同。
While these solutions work, they are unsatisfactory from an OOP point of view. 虽然这些解决方案有效,但从OOP的角度来看,它们并不令人满意。 To illustrate what I mean, let's take a concrete implementation of a snowman with each of these solutions and compare them with a simple object literal.
为了说明我的意思,让我们对每种解决方案分别进行一个雪人的具体实现,并将其与简单的对象文字进行比较。
Snowman 1: Save reference to return object 雪人1:保存对返回对象的引用
var snowman1 = (function(){
var _sayHello = function(){
console.log("Hello, my name is " + public.name());
};
var public = {
name: function(){ return "Olaf"},
greet: function(){
_sayHello();
}
};
return public;
})()
Snowman 2: Save reference to public function 雪人2:保存对公共功能的引用
var snowman2 = (function(){
var _sayHello = function(){
console.log("Hello, my name is " + name());
};
var name = function(){ return "Olaf"};
var public = {
name: name,
greet: function(){
_sayHello();
}
};
return public;
})()
Snowman 3: object literal 雪人3:物件文字
var snowman3 = {
name: function(){ return "Olaf"},
greet: function(){
console.log("Hello, my name is " + this.name());
}
}
We can see that the three are identical in functionality and have the exact same public methods. 我们可以看到这三个函数在功能上相同,并且具有完全相同的公共方法。
If we run a test of simple overriding, however 但是,如果我们测试简单覆盖
var snowman = // snowman1, snowman2, or snowman3
snowman.name = function(){ return "Frosty";}
snowman.greet(); // Expecting "Hello, my name is Frosty"
// but snowman2 says "Hello, my name is Olaf"
we see that #2 fails. 我们看到#2失败了。
If we run a test of prototype overriding, 如果我们进行原型覆盖测试,
var snowman = {};
snowman.__proto__ = // snowman1, snowman2, or snowman3
snowman.name = function(){ return "Frosty";}
snowman.greet(); // Expecting "Hello, my name is Frosty"
// but #1 and #2 both reply "Hello, my name is Olaf"
we see that both #1 and #2 fail. 我们看到#1和#2都失败了。
This is a really ugly situation. 这是一个非常丑陋的情况。 Just because I've chosen to refactor my code in one way or another, the user of the returned object has to look carefully at how I've implemented everything to figure out if he/she can override my object's methods and expect it to work!
仅仅因为我选择了以一种或另一种方式重构代码,返回对象的用户就必须仔细研究我如何实现一切以弄清楚他/她是否可以覆盖我的对象的方法并期望它能工作! While opinions differ here, my own opinion is that the correct override behavior is that of the simple object literal.
尽管此处的观点有所不同,但我个人的观点是正确的覆盖行为是简单对象文字的行为。
So, this is the real question: 因此,这才是真正的问题:
Is there a way to call a public method from a private one so that the resulting object acts like an object literal with respect to override behavior? 有没有一种方法可以从私有方法中调用公共方法,以使生成的对象在覆盖行为方面像对象文字一样工作?
You can use this
to get the object your privileged method greet
was called on. 你可以用
this
来让你的特权方法的对象greet
被称为上。
Then, you can pass that value to your private method _sayHello
, eg using call
, apply
, or as an argument: 然后,您可以将该值传递给您的私有方法
_sayHello
,例如,使用call
, apply
或作为参数:
var snowman4 = (function() {
var _sayHello = function() {
console.log("Hello, my name is " + this.name);
};
return {
name: "Olaf",
greet: function() {
_sayHello.call(this);
}
};
})();
Now you can do 现在你可以做
var snowman = Object.create(snowman4);
snowman.greet(); // "Hello, my name is Olaf"
snowman.name = "Frosty";
snowman.greet(); // "Hello, my name is Frosty"
And also 并且
snowman4.greet(); // "Hello, my name is Olaf"
snowman4.name = "Frosty";
snowman4.greet(); // "Hello, my name is Frosty"
With module pattern, you hide all the innates of an object in local variables/functions, and usually employ those in your public functions. 使用模块模式,您可以将对象的所有先天都隐藏在局部变量/函数中,并且通常在公共函数中使用它们。 Each time a new object is created with a module pattern, a new set of exposed functions - with their own scoped state - is created as well.
每次使用模块模式创建新对象时,也会创建一组新的公开函数-具有自己的作用域状态。
With prototype pattern, you have the same set of methods available for all objects of some type. 使用原型模式,您可以使用同一组方法来处理某种类型的所有对象。 What changes for these methods is
this
object - in other words, that's their state. 这些方法的变化是
this
对象-换句话说,就是它们的状态。 But this
is never hidden. 但是,
this
是从来没有隐藏。
Needless to say, it's tough to mix those. 不用说,很难将它们混合在一起。 One possible way is extracting the methods used by privates into a prototype of the module's resulting object with
Object.create
. 一种可能的方法是使用
Object.create
使用的方法提取到模块生成的对象的原型中。 For example: 例如:
var guardian = function() {
var proto = {
greet: function () {
console.log('I am ' + this.name());
},
name: function() {
return 'Groot';
}
};
var public = Object.create(proto);
public.argue = function() {
privateGreeting();
};
var privateGreeting = public.greet.bind(public);
return public;
};
var guardian1 = guardian();
guardian1.argue(); // I am Groot
var guardian2 = guardian();
guardian2.name = function() {
return 'Rocket';
};
guardian2.argue(); // I am Rocket
var guardian3 = guardian();
guardian3.__proto__.name = function() {
return 'Star-Lord';
};
guardian3.argue(); // I am Star-Lord
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.