Inheritance in JavaScript is based on the concept of prototype and the chaining of said prototypes. All JavaScript objects have a special property called prototype, which is a reference to another object. From this reference an object can inherit methods and properties. Any JavaScript object has its own prototype as well as its parent object and so on, making a chain.
There are multiple ways to build this chain. In this post I'm going to talk about the functional approach to make a prototype chain. In future posts I will discuss constructor functions and classes.
JavaScript has the method Object.create()
that receives two parameters: a prototype, and an object which contains the properties of the child to be created.
const jet = {
fly: function () {
console.log("flying at: " + this.speed);
},
};
This jet
object is a plain JavaScript object created with the curly braces syntax. The prototype of jet
is Object.prototype
, which is an internal object provided by JavaScript.
const combatJet = Object.create(jet, {
shoot: {
value: function () {
console.log("shooting: " + this.weapon);
},
},
});
The first parameter passed to Object.create
is the jet
object. The second parameter is another object which has the properties we want to add to combatJet
. When the combatJet
object is instantiated, combatJet.prototype
will be the jet
object, and combatJet
will have the shoot
property.
const f18 = Object.create(combatJet, {
speed: { value: "Mach 1" },
weapon: { value: "Minigun" },
});
The same thing happens when creating the f18
object, but we are using the combatJet
as its prototype. Also, we are adding the speed
and weapon
properties to the child object.
The resulting prototype chain is:
-
Object.prototype
is the prototype ofjet
-
jet
is the prototype ofcombatJet
-
combatJet
is the prototype off18
f18.shoot(); // Prints "flying at: Mach 1"
f18.fly(); // Prints "shooting: Minigun"
When calling f18.shoot()
the f18
object doesn't have the property shoot
. Then, JavaScript will check if their prototype (combatJet
) has it. combatJet.shoot
has a reference to this.weapon
. Typically, the this
keyword refers to the object on which the method was called. Thus, in f18.shoot()
the shoot
property refers to combatJet.shoot
, but this.weapon
has the value of f18.weapon
.
The result of the function call will be "shooting: Minigun"
The same situation occurs when calling f18.fly()
- Look for
fly
inf18
. It doesn't have the property - Look for
fly
incombatJet
which is the prototype off18
. It doesn't have the property either - Look for
fly
injet
which is the prototype ofcombatJet
. It does have the property - Execute the function
fly
.this
refers tof18
, sothis.speed
has a value of"Mach 1"
. The function call will print"flying at: Mach 1"
The instantiation of a combatJet
object could be refactored to a function for ease of use.
function createCombatJet(speed, weapon) {
return Object.create(combatJet, {
speed: { value: speed },
weapon: { value: weapon },
});
}
Top comments (0)