Reputation: 593
What are the technical reasons for using .prototype instead of declaring functions and members inside the object itself. It is easiest to explain with code examples.
What are the advantages of using:
RobsObject = function(data){
this.instanceID = data.instanceID;
this._formButton = document.getElementById('formSubmit_' + this.instanceID);
if(this._formButton)
{
//set a click listener that
//points to this._onSubmit, this._onSuccess, and this.onFailure
}
};
RobsObject.prototype = {
_onSubmit: function(type, args)
{
//make an ajax call
},
_onSuccess: function(type, args)
{
//display data on the page
},
_onFailure: function(type, args)
{
//show an alert of some kind
},
};
As oppose to declaring your functions inside of the Object like:
RobsObject = function(data){
this.instanceID = data.instanceID;
this._formButton = document.getElementById('formSubmit_' + this.instanceID);
if(this._formButton)
{
//set a click listener that
//points to this._onSubmit, this._onSuccess, and this.onFailure
}
this._onSubmit = function(type, args)
{
//make an ajax call
}
this._onSuccess = function(type, args)
{
//display data on the page
}
this._onFailure = function(type, args)
{
//show an alert of some kind
}
};
Thanks.
Edit: As many of you have pointed out my functions in the second code snippet should have 'this' in front of them in order to be public. So I added it. Just a mistake on my part.
Upvotes: 4
Views: 456
Reputation: 10716
Everything declared in a constructor function's prototype
is shared by all instances of that constructor function. If you define functions in the constructor function, then each instance gets its own copy of the function, which wastes memory (and could potentially cause problems if you compare properties between two instances later).
Also, in your example the functions declared in the constructor function are private to the scope of the function. They cannot be called as member methods on instances. For that you would need to assign them to properties of the object:
MyObject = functon() {
// ...
this.myMethod = function() {
// ...
};
}
Douglas Crockford has a good write-up of prototypical inheritance that is definitely worth checking out: Prototypical Inheritance in JavaScript.
UPDATE: Brief Prototype Summary
When you create a new object using a constructor function, the value of the function's prototype
property is assigned as the new object's prototype object. (Yes, the names are confusing!) This is a lot like assigning a superclass in a class-based language (but not quite! Read Crockford's page!)
// MyObject constructor function:
MyObject = function() {
this.a = 1;
}
// Define an object to use as a prototype.
var thePrototype = { b: 2 };
// Assign thePrototype as the prototype object for new instances of MyObject.
MyObject.prototype = thePrototype;
// Create an instance of MyObject.
var x = new MyObject();
// Everything in thePrototype is available to x.
console.log(x.b);
// x's prototype is a reference to thePrototype, so updating it affects x.
thePrototype.c = 3;
console.log(x.c);
// Setting properties on x always sets them *on x*, even if the property is
// defined on the prototype:
x.b = 0;
y = new MyObject();
console.log(x.b);
console.log(y.b);
Upvotes: 14
Reputation: 23803
In the first case, an object constructed with new RobsObject()
has the functions _onSubmit()
, _onSuccess()
as it's properties. They are so-called the public functions of the object.
In the second case, those functions are not properties of new RobsObject()
. However, they would be visible to any of the 'public' functions (there aren't any, in your case). In effect, they are the private functions.
However, if you wrote your second snippet this way...
RobsObject = function(data){
this.instanceID = data.instanceID;
this._formButton = document.getElementById('formSubmit_' + this.instanceID);
if(this._formButton)
{
//set a click listener that
//points to this._onSubmit, this._onSuccess, and this.onFailure
}
this._onSubmit = function(type, args)
{
//make an ajax call
}
this._onSuccess = function(type, args)
{
//display data on the page
}
this._onFailure = function(type, args)
{
//show an alert of some kind
}
};
the result is the same.
An important difference between these two conventions is that in the first method, you can't define private functions that can be shared between many public functions like you do in the second method. The Object literal used to define the prototype does not form closures like a function body.
For example,
function MyConstructor() {
var myPrivate = function() {
}
this.myPublic1 = function() {
myPrivate();
}
this.myPublic2 = function() {
myPrivate();
}
}
myPrivate()
is a function that is visible to both public functions.
Upvotes: 0
Reputation: 58251
The answer is memory. If you put the members inside of the object itself, then EVERY instance of that object will contain (in memory) all members. If you use prototype, on the other hand, it only exists once, and all instances will access those members as if they were their own.
Upvotes: 3