Here is one way to see the difference:
var circle1 = circle(1);
var circle2 = circle(1);
alert(circle1.area == circle2.area);
For Method1 you will see false
while Method2 yields in true
. That's because in the first case you assign a new closure function to each object created, two objects end up with different area
functions even though both do the same thing. In the second case the objects share the same prototype object with its area
method, that method is of course identical in both cases.
Usually Method2 is preferable for several reasons:
- Object creation is faster because only custom properties need to be initialized.
- You don't waste memory on instantiating multiple copies of the same thing.
- You can easily find out which of the object properties have custom values by calling
Object.hasOwnProperty
.
There are some disadvantages as well to keep in mind.
- You always spend time on setting up the prototype even if you never create any objects.
- Property access is slightly slower because the JavaScript engine needs to check object properties first and then the properties of the prototype object (modern JavaScript engines optimize this pretty well however).
- There is a common fall trap of putting objects or arrays on the prototype, these will be shared between all object instances.
Here is an example of the common mistake:
function NumberCollection()
{
}
NumberCollection.prototype = {
numbers: [],
sum: function()
{
var result = 0;
for (var i = 0; i < this.numbers.length; i++)
result += this.numbers[i];
return result;
}
}
var c1 = new NumberCollection();
c1.numbers.push(5);
alert(c1.sum()); // Shows 5
var c2 = new NumberCollection();
c2.numbers.push(6);
alert(c2.sum()); // Oops, shows 11 because c1.numbers and c2.numbers is the same
The correct approach here would be:
function NumberCollection()
{
this.numbers = [];
}
NumberCollection.prototype = {
numbers: null,
sum: function()
{
var result = 0;
for (var i = 0; i < this.numbers.length; i++)
result += this.numbers[i];
return result;
}
}