Inheritance is a way to allow one object to share functionality with another object, without re-typing code, as well as adding its own feature without affecting the original object. The object that is inherited from is called the parent and the object that is inheriting is called the child. Inheritance is a feature of Object Orientated Programming and is important to understand when doing OOP.
Within JavaScript an object can be created from a function, the parameters of the function can then be used to set up and initialise values within each instance. The functional object below is called 'Person' and takes two parameters, which are used to set the first name and the last name of each person. There is one method within the Person object call 'getFullName' which returns a concatenation of both the first and last name separated by a space.
function Person(fn, ln){
this.firstName = fn;
this.lastName = ln;
this.getFullName(){
return this.firstName + " " + this.lastName;
}
}
Each object within JavaScript has its own 'prototype'. The above code will create a new function called 'getFullName' whenever a new instance of the object is created, which can result in multiple instances of this function store in memory per instance. Using the prototype of an object can solve this problem, as the function will be attached to the object rather than each instance. The below code shows how to add a function to the prototype of the 'Person' object, this can also be used to add variables to objects rather than instances.
function Person(fn, ls){
this.firstName = fn;
this.lastName = ln;
}
Person.prototype.getFullName = function(){
return this.firstName + " " + this.lastName;
}
We can then make another object to inherit from the Person object. Below is a simple Teacher object that just has one field called 'subject', as we will inherit from the Person object and be able to get a first name and last name without having to explicitly write the code.
function Teacher(sbj){
this.subject = sbj;
}
First, the constructor of the Teacher object has to be changed. We need to add parameters for the first name and last name, as we will still need to pass these values to new instance of the Teacher so they can then be passed down the inheritance chain. Then we need to use the 'call' method on the Person object. The call method effectively calls the constructor of another object, in this each it called the constructor of the Person object. The first parameter of the call method if the context in which to call the constructor, we are passing 'this' in which refers to the instance of the Teacher object. This means that the Teacher object will get the fields and methods from the Person object but within itself. We then pass the other parameters into the Person constructor as normal.
function Teacher(fn, ln, sbj){
Person.call(this, fn, ln);
this.subject = sbj;
}
There are few more adjustments to the Teach object required before the inheritance is completed. The prototype of the Teacher is still pointing towards the Teacher prototype, this means we will not have the method 'getFullName' within the Teacher object as that is placed onto the 'Person.prototype'. When setting the prototype of the Teacher to match the Person prototype we use the 'Object.create' method to ensure a new instance of the prototype is created, as we don't want to affect the Person prototype when adding stuff to the Teacher prototype. However, now the constructor of the Teacher object is actually a Person constructor, as the constructor function is held within the prototype object, this means we also have to change that back to the Teacher constructor.
Teacher.prototype = Object.create(Person.prototype);
Teacher.prototype.constructor = Teacher;
Now that we have set up the inheritance completely we can create a new instance of the Teacher object and pass in values for the first name, last name, and subject. Within the example code below we are able to access the 'getFullName' method from the Person object and we can access the 'subject' field of the Teacher object.
var t = new Teacher("John", "Doe", "History");
console.log(t.getFullName());
console.log(t.subject);
To ensure the inheritance works as we expected we can use the 'instanceof' keyword to check if one object is an instance of another. The below example shows checking if the newly created Teacher object is both an instance of a Teacher and of a Person. Both these statements will return true.
console.log(t instanceof Teacher);
console.log(t instanceof Person);
The person object still works in the same way as it did before, without any adverse effects. We can create a new instance of a Person and call the 'getFullName' method. However, the 'subject' field is not defined and will result in 'undefined', as that is not part of the Person object.
var p = new Person("Jane", "Doe");
console.log(p.getFullName());
console.log(p.subject);
We can also use the 'instanceof' keyword to check the Person object has not been affected. The first statement checks if the object is an instance of Person, which will return true. The second statement is checking if the object is an instance of a Teacher, which will return false. All teachers are people but not all people are teachers.
console.log(p instanceof Person);
console.log(p instanceof Teacher);
Below is the full code, showing the setup of the Person and Teacher object, with all the lines needed to set up the inheritance between the Teacher and the Person objects.
function Person(fn, ln){
this.firstName = fn;
this.lastName = ln;
}
Person.prototype.getFullName = function(){
return this.firstName + " " + this.lastName;
}
function Teacher(fn, ln, sbj){
Person.call(this, fn, ln);
this.subject = sbj;
}
Teacher.prototype = Object.create(Person.prototype);
Teacher.prototype.constructor = Teacher;
This article was originally posted on my website: https://acroynon.com/
Top comments (2)
Thanks for the reminder how inheritance works in JS.
I'm glad that with ES2015 we have classes and defining inheritance between objects is now straightforward, no need to touch prototypes anymore.
Thank you for the comment, I really appreciate it. I agree, the new class system in JavaScript is so useful. The prototype chain can get so complicated when manually trying to manipulate objects.