如何在JavaScript模塊模式中通過私有函數調用公共函數?如何在JavaScript模塊模式中通過私有函數調用公共函數
例如,在下面的代碼,
var myModule = (function() {
var private1 = function(){
// How to call public1() here?
// this.public1() won't work
}
return {
public1: function(){ /* do something */}
}
})();
這個問題已經被問twicebefore,爲每個不同的接受的答案。
儘管這些解決方案有效,但從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失敗。
這是一個非常醜陋的情況。僅僅因爲我選擇以這種或那種方式重構我的代碼,返回對象的用戶必須仔細查看我是如何實現一切的,以確定他/她是否可以重寫我的對象的方法並期望它可以工作!雖然意見不同,但我自己的看法是,正確的重寫行爲是簡單對象字面值的行爲。
所以,這是真正的問題:
有沒有辦法從一個私人調用一個公共方法,這樣得到的對象的行爲像一個對象文本相對於覆蓋的行爲呢?
在你討論的陷阱中有一個重要的註釋:我對模塊模式的理解是,它真的是JS的原型/ OOP多態論方法的替代。因此,我認爲你應該避免使用這兩者 - 我不認爲這是一個陷阱*本身*。 – EyasSH
@ EyasSH - 它可以這樣使用,但我認爲它更像是一種可以用於繼承而不是故意特徵的人工製品。它似乎主要用於模擬私人成員(或者不公開別人不應該玩的東西),也可以提高性能。 – RobG
@RobG,沒錯,但是你可以在閉包中聲明私有函數,同時堅持原型模式。在那種情況下,使用'''this'''很好。我的觀點是,如果你正在使用模塊模式,我認爲看模塊<->原型交互怪異不是一個真正的理由不使用一種方法。如果你認爲誰在使用你的代碼將會這樣做,那麼這可能是一個堅持原型的原因。 – EyasSH