Consider this first Javascript snippet, which only uses var and this to declare scope:
var Bro = function() {
var self = this;
this.storyName = "story"; // public
var storyType = "cool"; // private
// private function
var composeStory = function() {
return storyType + ' ' + self.storyName;
};
// privileged function
this.tellStory = function() {
console.log(composeStory() + ' bro!');
};
};
Compared to this, which uses a return statement, and modifies the scope somewhat:
var Bro = function() {
var self = this;
this.storyName = "story"; // private?
var storyType = "cool"; // private
// private function
var composeStory = function() {
return storyType + ' ' + self.storyName;
};
// privileged variables/functions
return {
storyName: this.storyName,
tellStory: function() {
console.log(composeStory() + ' bro!');
}
};
}
My question then is:
- When would you use the second method over the first, or is this just a stylistic thing?
- Why is
this.storyNamein the second example private, even though I set it onthis? - I had to declare
var self = this;in order to get access to thethisscope inside both private functions. How do Javascript frameworks make thethisobject accessible inside their functions? - In the second example, the
storyNameproperty in the return statement could access thethisscope properly. Why can it do that, when the private function could not?
There is no such thing as “private” and “public” in Javascript. What you are seeing is the difference between properties on an object and closure captured variables. Closure capture variables can be used to hide state but they are hiding it on a different object attached to the functions created in the closure scope, not on the object being returned, as in other languages. With that in mind I will answer your questions,
1) I wouldn’t user either form but they are stylistically similar, both are using closure capture. Note, however, the first uses the constructor pattern and the second uses a factory pattern. The first will only work if you use the new keyword prior to calling Bro the second will ignore the object created by new in favor of the object created by the object literal, but you can call it safely without prefixing it with new.
2) storyName is not private, it is set on a different object. When a function is called prefixed by new a fresh object is created and passed in as the “this” parameter. This is the object you are setting by “this.storyName”. This object is then discarded in favor of the object you create in the literal. You don’t see storyName because it wasn’t set on the object returned.
3) You can capture this in a closure variable like self or use bind on the function to bind this to the original this. I prefer closure capture myself.
4) The this is still in scope because you are executing in the constructor function.