I try to understand the prototype-based inheritance in JavaScript. To establish a prototype chain with constructor functions, you usually do it this way:
function Person( name, gender ){
this.name = name;
this.gender = gender;
}
function Male( name ){
Person.call(this, name, "male");
}
Male.prototype = Object.create( Person.prototype );
Object.defineProperty( Male.prototype, "constructor", {
enumerable: false, value: Male, writeable: true
});
var person1 = new Male( "Chris" );
So, for Male.prototype you create a completely new object which has the internal [[prototype]] property set to the parent object. Because it is a new object, you still have to add a non-enumerable constructor property.
Since there is a way to set the [[prototype]] property directly, I wonder why you can't do this:
function Person( name, gender ){
this.name = name;
this.gender = gender;
}
function Male( name ){
Person.call(this, name, "male");
}
Object.setPrototypeOf( Male.prototype, Person.prototype );
var person1 = new Male( "Chris" );
With this solution you just set the [[prototype]] property of Male.prototype to the parent object. (Before ES6 you could have used the __proto__ property to set the prototype.) You don't need to create a new object (because as far as I know the js runtime automatically attaches a new prototype object to every function) and you don't need to create the correct constructor property explicitly, because it is already there.
My question is: why does nobody use this approach to set the prototype chain? Where is the problem?
This is a subtle but VERY important point. If you set the
Maleprototype to thePersonprototype, they will be sharing ONE instance of an object. Any changes to thePersonprototype will affect ALL instances of both thePersonandMaleobjects and vice versa. Now, initially, this seems like the desired behavior, but you have to keep the concepts of "types" separate from "instances" here.By giving
Malea new instance ofPersonas its prototype, you gain the benefits of inheritance, but you de-couple the actual instance ofPersonthat allPersoninstances are using from the instance that allMaleinstances will use.This allows you to make changes to the
Male.prototypewithout affecting anyPersoninstances.