I think the difference has clicked in my head, but I’d just like to be sure.
On the Douglas Crockford page Prototypal Inheritance in JavaScript, he says
In a prototypal system, objects inherit from objects. JavaScript,
however, lacks an operator that performs that operation. Instead it
has a new operator, such that new f() produces a new object that
inherits from f.prototype.
I didn’t really understand what he was trying to say in that sentence so I performed some tests. It seems to me that the key difference is that if I create an object based on another object in a pure prototypal system, then all the parent parent members should be on the prototype of the new object, not on the new object itself.
Here’s the test:
var Person = function(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.toString = function(){return this.name + ', ' + this.age};
// The old way...
var jim = new Person("Jim",13);
for (n in jim) {
if (jim.hasOwnProperty(n)) {
console.log(n);
}
}
// This will output 'name' and 'age'.
// The pure way...
var tim = Object.create(new Person("Tim",14));
for (n in tim) {
if (tim.hasOwnProperty(n)) {
console.log(n);
}
}
// This will output nothing because all the members belong to the prototype.
// If I remove the hasOwnProperty check then 'name' and 'age' will be output.
Is my understanding correct that the difference only becomes apparent when testing for members on the object itself?
Your assumptions are correct, but there is another pattern that Douglas doesn’t talk much about – the prototype can be used for properties as well. Your person class could have been written as:
In this case, iterating over properties of an instance of this class, as you do in your example, would generate no output for the ‘gender’ property.
EDIT 1:
The assignment of name and age in the constructor do make the properties visible by hasOwnProperty (thanks @matt for reminding me of this). The unassigned gender property would not be visible until someone sets it on the instance.
EDIT 2:
To further add to this, I present an alternative inheritance pattern – one that I have personally used for very large projects:
This is a fairly common pattern with a small twist – the parent class is attached to the child via the “superclass” property permitting you to access methods/properties overridden by the child. Technically, you could replace
OldPerson.superclasswithPerson, however that is not ideal. If you ever changed OldPerson to inherit from a class other than Person, you would have to update all references to Person as well.EDIT 3:
Just to bring this full circle, here is a version of the “inherits” function which takes advantage of Object.create and functions exactly the same as I previously described: