如何在JavaScript模块模式中从私有函数中调用公共函数?
例如,在以下代码中,
我们可以看到这三个在功能上完全相同,并且具有完全相同的公共方法。
我们可以看到, #1 和 #2 都失败了。
这是一个非常丑陋的情况。仅仅因为我选择以某种方式重构我的代码,返回对象的用户就必须仔细查看我如何实现所有内容,才能确定他 / 她是否可以覆盖我的对象方法并期望它正常工作!虽然在这里意见不一,但我个人认为正确的覆盖行为是简单对象文字的行为。
所以,这是真正的问题:
有没有办法从私有方法调用公共方法,以便生成的对象对于覆盖行为的行为类似于对象文字?
例如,在以下代码中,
var myModule = (function() {
var private1 = function(){
// How to call public1() here?
// this.public1() won't work
}
return {
public1: function(){ /* do something */}
}
})();
这个问题已经两次 被问到了, 并且每次都有一个不同的被接受的答案。
虽然这些解决方案可行,但从OOP的角度来看,它们并不令人满意。为了说明我的意思,让我们以一个具体的雪人实现为例,比较它们与一个简单的对象文字。
雪人 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;
})()
雪人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;
})()
雪人 3:对象字面量
var snowman3 = {
name: function(){ return "Olaf"},
greet: function(){
console.log("Hello, my name is " + this.name());
}
}
我们可以看到这三个在功能上完全相同,并且具有完全相同的公共方法。
然而,如果我们进行简单覆盖的测试
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"
我们发现 #2 失败了。
如果我们运行原型覆盖的测试,
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"
我们可以看到, #1 和 #2 都失败了。
这是一个非常丑陋的情况。仅仅因为我选择以某种方式重构我的代码,返回对象的用户就必须仔细查看我如何实现所有内容,才能确定他 / 她是否可以覆盖我的对象方法并期望它正常工作!虽然在这里意见不一,但我个人认为正确的覆盖行为是简单对象文字的行为。
所以,这是真正的问题:
有没有办法从私有方法调用公共方法,以便生成的对象对于覆盖行为的行为类似于对象文字?
this
是可以的。我的观点是,如果你正在使用模块模式,那么我认为查看模块<->原型交互的奇怪行为不是不使用该方法的真正原因。如果你认为使用你的代码的人会这样做,那么坚持使用原型可能是一个理由。 - EyasSHsnowman1
、snowman2
和snowman3
的末尾添加()
,否则它们将成为函数。另外,在原型覆盖中,你可能需要自定义snowman.name
,否则我不知道它如何输出“Frosty”。 - Oriol