Original Article: JavaScript — Inheritance, delegation patterns and Object linking
Author: NC Patro
Learn about inheritance, delegation patterns, and objects linked to other objects in JavaScript (prototype inheritance).
What is Inheritance#
In most class-based object-oriented languages, inheritance is a mechanism that allows one object to acquire all the properties and methods of another object. Although the class
keyword was introduced in ES2015
, JavaScript is not a class-based language. It is merely syntactic sugar and fundamentally still relies on the prototype chain.
Classical Inheritance vs. Prototype Inheritance#
Classical Inheritance (Non-JavaScript)#
Vehicle
is the parent class, andv1
andv2
are instances ofVehicle
.Car
is a subclass ofVehicle
, andc1
andc2
are instances ofCar
.- When we inherit a class, classical inheritance creates a copy of the behavior from the parent class to the child class, and then the parent and child classes become independent entities.
- This is like building a car using tools and car blueprints, but once they are built, they are separate entities because it is a copy and there is no connection between them. This is why all arrows point downwards (properties and behavior are passed down).
Prototype Inheritance (Delegation Pattern)#
v1
andv2
are linked toVehicle.prototype
because they are created usingnew
.- Similarly,
c1
andc2
are linked toCar.prototype
, andCar.prototype
is linked toVehicle.prototype
. - In JavaScript, when we create an object, it does not copy properties or behavior, but instead creates a link. The same applies when inheriting a class.
- Compared to classical non-JavaScript inheritance, all the links point in the opposite direction because it is a delegation pattern. These links are called the prototype chain.
- This pattern is called the delegation pattern and is commonly known as prototype inheritance in JavaScript.
You can refer to this article JavaScript-Prototypes for a deeper understanding of the prototype chain.
Example of Prototype Inheritance#
- Implementing classical inheritance using
Object.create()
. - In the code snippet below,
Car.prototype
andVehicle.prototype
are connected using theObject.create()
function.
// Vehicle - Superclass
function Vehicle (name) {
this.name = name;
}
// Superclass method
Vehicle.prototype.start = function () {
return "engine of " + this.name + " starting...";
}
// Car - Subclass
function Car (name) {
Vehicle.call(this, name); // Call the superclass constructor
}
// Subclass extends superclass
Car.prototype = Object.create(Vehicle.prototype);
// Subclass method
Car.prototype.run = function () {
console.log("Hello " + this.start());
}
// Subclass instances
var c1 = new Car("Fiesta");
var c2 = new Car("Baleno");
// Access the subclass method that internally accesses the superclass method
c1.run(); // "Hello engine of Fiesta starting..."
c2.run(); // "Hello engine of Baleno starting..."
- In the above code, due to the prototype chain, the object
c1
can access therun()
andstart()
methods. As shown in the diagram below, we can see thatc1
does not have these methods, but it has a link upwards. - The
this
in the above code is simply the current execution context of each method, i.e.,c1
andc2
.
You can browse this article JavaScript-All About this and new Keywords for a detailed understanding of the this keyword.
Diagram representation of the above code:
Objects Linked to Other Objects#
- Now let's simplify the previous inheritance example code and focus only on the links between objects.
- So we will try to remove the
.prototype
,constructor
, andnew
keywords and only consider objects. - We will use the
Object.create()
function to create all the links between functions.
Here is a simplified version of the previous example code:
// Base object with an initialization method
var Vehicle = {
init: function (name) {
this.name = name;
},
start: function () {
return "engine of " + this.name + "starting...";
}
}
// Delegation link created between the sub object and the base object
var Car = Object.create(Vehicle);
// Sub object method
Car.run = function () {
console.log("Hello " + this.start());
};
// Instance objects with delegation links pointing to the sub object
var c1 = Object.create(Car);
c1.init('Fiesta');
var c2 = Object.create(Car);
c2.init('Baleno');
c1.run(); // "Hello engine of Fiesta starting..."
c2.run(); // "Hello engine of Baleno starting..."
Diagram representation of the above code:
- Now we can see how we eliminate the complexity of
new
,.prototype
, constructor, and method invocation in the code while still achieving the same result. - The only important thing is that
c1
is linked to one object and then linked to another object, and so on. - This is also known as the object delegation pattern.
Summary#
It is important to understand prototype inheritance and the prototype chain before using prototype inheritance and the prototype chain in code to avoid complexity.
Reference: You Don't Know JS series