5. Inheritance
Follow along with code examples here!
Table of Contents:
Key Concepts
Inheritance describes a relationship between two classes: a subclass that inherits methods from a superclass. Instances of the subclass can reuse and add to the methods defined in a superclass.
The
Subclass extends Superclasssyntax defines an inheritance relationship between two classesThe
superkeyword references the superclass of a given subclass:We can invoke
super()in the subclass constructor to invoke the superclass'sconstructor().We can invoke
super.method()in an overridden method to invoke the superclass's version of the method on the subclass instance.
The prototype chain describes the linked structure where each object inherits methods from a prototype, which may inherit methods from another prototype, forming a chain.
When you access a property or method, JavaScript walks up this chain until it finds what you're looking for (or reaches the end).
Inheritance
A Person and a Student
Consider this Person class.
I want to make another class called Student that can do everything a Person can. In addition, Student will have some additional properties and methods.
Question: What similarities and differences do you see between these two classes? What coding style rule is this breaking?
A Student has every property and method that a Person has but it also has the public field courses as well as the properties subject and sschool. The introduce() method is implemented slightly differently and the enrollInCourse method is new.
This code breaks the DRY principle (Don't Repeat Yourself). In the Student class we duplicate the code for the fullname method and most of the code in the constructor and introduce methods stays the same.
extends
extendsA Student is essentially a specific kind of Person. In computer science, we would say that "a Student is a Person" to describe this relationship.
In JavaScript, we formalize this relationship using the Subclass extends Superclass syntax:
With just this extends keyword, every instance of Student "inherits" the properties and methods from the Person class.
Furthermore, instances of Student are also instances of Person.
super
superWe don't want our Student class to just be a carbon-copy of the Person class. When we want to add new functionality to a subclass and still leverage the functionality of the superclass, we use the super keyword.
The super keyword references the superclass of a given subclass. super allows us to extend the functionality of the superclass's methods:
This example shows the two common usages of the super keyword:
super()— invokes the superclass constructorIn the
Studentconstructor,super()invokes thePerson's constructor which assigns the propertiesfirstName,lastName, andageto the newStudentinstance.
super.method()— invokes a method defined in the superclass. Often used to override the behavior of that method while still using some of the behavior from the superclass.The
introduce()method is overridden in theStudentclass but usessuper.introduce()to invoke theintroducemethod defined in thePersonclass.
Notice that the fullName method is inherited from the Person class and is NOT overridden. It will behave the same way for student instances and person instances.
Challenge: Professor Class
Create a class called Professor that is a subclass of Person with the following behavior:
Then, create class called MarcyStudent that is a subclass of Student.
All instances of
MarcyStudentshould havesubjectbe set to"Software Engineering"andschoolbe set to"Marcy Lab School".It should have a static
validCoursesarray:['Leadership & Development', 'Technical Interview Prep', 'Technical Lecture']enrollInCourseshould be overridden to first check if the provided course is in thevalidCoursesarray before adding the course to thecoursesarray.
Prototype Chain: Subclasses of Subclasses
Array.prototype
Have you considered how arrays are able to use methods like push and forEach?
If we look at the "own properties" of an array (the properties defined on the array), we don't see any of its methods:
As we can see, the properties of an array are just the indexes for each value and the length property. So, where are those methods defined?
We get a hint if we look at the documentation for the array method push(). Notice how it names the method as Array.prototype.push?
Arrays are able to use array methods because:
Methods like
pushandforEachare defined as methods of theArrayclass and are therefore inherited by allArrayinstances. We can see those methods by looking at the properties of theArray.prototypeobject.Whenever we create an "array literal" (using square brackets
[]), we are actually creating a new instance of theArrayclass!
Object.prototype and the Prototype Chain
Now, in that list of Array.prototype methods, can you find a method called hasOwnProperty?
It's not there, and yet we can invoke that method on an Array instance:
The Object.prototype.hasOwnProperty method is defined as a part of the Object class from which all classes are extended, including the Array class and the classes we've made here like Person and Student.
Since arrays are instances of the Array class which extends the Object class, we end up with what we call a prototype chain: a linked structure of objects inheriting methods from class prototypes, which can inherit methods from other class prototypes, and so on...
letters → Array.prototype → Object.prototype → null
The prototype chain is used by JavaScript to find method definitions when the method can't be found the object invoking the method.
For example, when letters.push() is invoked, JavaScript looks at letters to see if it has the definition of push. When it doesn't find it, it looks at inside of Array.prototype where it finds the definition of push.
When letters.hasOwnProperty() is invoked, JavaScript looks at letters, then Array.prototype, and then finally at Object.prototype to find the definition.
If we were to invoke a non-existent method like letters.foo(), JavaScript would look at letters, then Array.prototype, then Object.prototype and then would run out of prototypes to look at. At this point, JavaScript would determine that foo is not a function and throw a TypeError.
Quiz!
Consider the ada instance of the Student class below.
Q: Using arrows, draw out the prototype chain for ada.
ada → Student.prototype → Person.prototype → Object.prototype → null
Consider the code below:
Q: For each line of code, describe how JavaScript walks up the prototype chain and where it finds the definition.
.fullName() is not in ada so JavaScript looks at Student.prototype, then Person.prototype where it finds the definition. .toString() is not in ada so JavaScript looks at Student.prototype, then Person.prototype, then Object.prototype where it finds the definition. .fullName() is found in ada so JavaScript doesn't do anything. .introduce() is not in ada so JavaScript looks at Student.prototype where it finds the definition. It ignores the definition in Person.prototype because it has found a "closer" definition. .blah() is not in ada so JavaScript looks at Student.prototype, then Person.prototype, then Object.prototype. It doesn't find it there so JavaScript throws a TypeError.
If you run the Node debugger, you can see the prototype chain by looking at the [[Prototype]] field of any object:z

Practice & Review
Study Questions
Then, with a partner, discuss these questions:
Question 1: What does extends do?
extends makes the WebDeveloper inherit methods from Programmer. It sets Programmer.prototype as the prototype for WebDeveloper
Question 2: What does super do?
super() invokes the Programmer constructor function using its own value of this. Any properties that the Programmer constructor sets on this will be set on WebDeveloper.
Question 3: What do we know about the relationship between a Programmer and a Person?
WebDeveloperis said to be a subclass ofProgrammer.Programmeris said to be a superclass ofWebDeveloper.WebDeveloperwill inherit properties and methods fromProgrammerandPerson.Instances of
WebDeveloperare also instances ofProgrammerand ofPerson, but not all instances ofPersonorProgrammerare instances ofWebDeveloper.
Last updated