How do I call a public function from within a private function in the JavaScript Module Pattern?
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.
- Save a reference to the return object before returning it, and then use that reference to access the public method. See answer.
- Save a reference to the public method in the closure, and use that to access the public method. See answer.
While these solutions work, they are unsatisfactory from an OOP point of view. 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
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
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
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.
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.
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?
this
is fine. My point is, if you are using the module pattern, I think looking at module<->prototype interaction weirdness is not a real reason not to use an approach. It might be a reason to stick to prototypes altogether if you think whoever is using your code will do that.. – Bellows()
at the end ofsnowman1
,snowman2
andsnowman3
, or otherwise they will be functions. And probably in the prototype overriding you should customizesnowman.name
, or otherwise I don't see how it should output "Frosty". – Sharonsharona