Grasping prototypical Inheritance through pseudoclassical instantiation (JavaScript)
When using constructor functions for inheritance in JavaScript, you:
-
Make the
prototype
property of the "derived" constructor an object whose prototype is theprototype
property of the "base" constructor. -
Set the
constructor
property on the "derived" constructor'sprototype
property to point to the "derived" constructor. -
Call the "base" constructor from the "derived" constructor with the correct
this
.
Like this:
var Infant = function() {
this.age = 0;
this.color = 'pink';
this.food = 'milk';
};
Infant.prototype.eat = function(){
return /*...something...*/; // Returning `this.eat` doesn't make any sense, that's the function we're in
};
var Adolescent = function() {
// #3 Give super a chance to initialize the instance, you can pass args if appropriate
Infant.call(this);
this.age = 5;
this.height = 'short';
this.job = 'keep on growing';
};
// Set up Adolescent's prototype, which uses Infant's prototype property as its prototype
Adolescent.prototype = Object.create(Infant.prototype); // #1
Object.defineProperty(Adolescent.prototype, "constructor", // #2
value: Adolescent,
writable: true,
configurable: true
});
// (In pre-ES5 environments that don't event have `Object.defineProperty`, you'd use
// an assignment instead: `Adolescent.prototype.constructor = Adolescent;`
Object.create
was added in ES5, so it won't be present on obsolete JavaScript engines like the one in IE8. The single-argument version of it used above can be easily shimmed, though.
In ES2015 we have the option of doing it with the new class
semantics:
class Infant {
constructor() {
this.age = 0;
this.color = 'pink';
this.food = 'milk';
}
eat() {
return /*...something...*/;
}
}
class Adolescent extends Infant { // extends does #1 and #2
constructor() {
super(); // #3, you can pass args here if appropriate
this.age = 5;
this.height = 'short';
this.job = 'keep on growing';
}
}