Introduction
JavaScript is the most widely used programming language, however a large number of programmers keep working with JavaScript without knowing the nuances of it. Inheritance support in JavaScript is another such feature which often confuses programmers who learn JavaScript as their secondary programming language and come from OOP background like C# and Java.
This post is my effort to elucidate inheritance in JavaScript, how and why it’s useful and all the moving part which make it work, and lastly how to mimic the classical inheritance model in JavaScript.
Prototypal Inheritance
Functions are the first class objects in JavaScript, what does that mean? It means Functions get special treatment everywhere in the language. Let’s consider a very simple function as shown below:
function Animal() {
}
var animal = new Animal();
As simple as the code written above is, it does fairy complex things underneath. “Function
” is a global function and every function in JavaScript is an object of “Function
” function, yes and that’s not a typo.
Things which happen after the above piece of code is called can be visualized as shown in the following diagram:
While reading further please keep in mind that,
a) All javascript functions have "prototype" property.
b) All javascript objects have an internal link "__proto__" and it refers to that object's constructor function's prototype. (Keep reading it will be clear).
Let’s go through the above diagram in a little more detail.
- “
Animal
” function object is created. Animal
gets assigned a property named “prototype
” and a new object is assigned as the value of Animal
object’s “prototype
” property, I’ll refer to this object as “Animal.prototype
”. Animal.prototype
object get a property named “constructor
” which points back to the “Animal
” function object itself. Animal.prototype
object has an internal link to another object, which can be retrieved by its “__proto__
” property. This internal linking does all the magic which enables the inheritance in JavaScript. “__proto__
” of Animal.prototype
points to another object which is nothing but the “Object.prototype
”. - Since "Object" and "Animal" both are javascript functions and also an object of global function "Function",
both have internal link "__proto__" which points to "Function.prototype". - “
__proto__
” property of “Object.prototype
” points to null. - “
null
” object is where the inheritance chain ends. - For each function call like "
new Animal()
", a new object will be created and all such objects will have the internal link __proto__
to Animal.prototype
. - Finally where does "Function.__proto__" link points to? well it points to the same object which "Function.prototype" points to.
Note: Use of __proto__ is debatable because it was not originally included in the ECMASCRIPT specification but in ECMASCRIPT 6 it has been included in the specification and has been standardized. There are other ways we can access the link object, I’ll mention those methods later in this article.
When we create a new object of function “Animal
” using “new Animal()
”, then a new empty object is created and “Animal.prototype
” is set to its internal link “__proto__
”.
What’s the Deal with Internal Link “__proto__”?
The internal link “__proto__
” we have seen above does all the magic called Prototypal inheritance in JavaScript. When we try to access any property (or method) of an object in JavaScript, then JavaScript walks through the entire chain of objects using internal link “__proto__
” to find that property, till it finds the property in any of the objects or reaches the “null
” object.
In prototypal inheritance object inherit properties from object dynamically this is different from classical inheritance where Classes (blueprints of objects) inherit from other Classes.
That’s a very powerful feature of JavaScript and that makes it so cool.
Let’s take another example:
var Person = function (name) {
this.name = name;
}
Person.prototype.age = 24;
var person1 = new Person("Mike");
In the above piece of code, we have created a simple constructor function “Person
”. Theoretically, any function in JavaScript can act like a constructor function and by convention, we name constructor functions starting with a capital letter. However constructor functions are only useful if they are written in a certain way. I’ll discuss more about them later in this article.
We add “age
” property to functions prototype. Next let’s create an object of this function using new
keyword “person1
”, and print out all the properties of person1
using the following piece of code:
for (var p in person1) {
if (person1.hasOwnProperty(p)) {
console.log(p);
}
}
Output or the above code is “name
” unsurprisingly.
So we can see we have only “name
” property in person1
object. Let’s run the following piece of code.
console.log(person1.age);?
And we can see it does print out 24
, so even though person1
object does not have “age
” property, we can still access its value because its prototype has that property.
Accessing any Object's Prototype
- As shown earlier, you can access it using “
__proto__
” property. - You can also access any objects prototype using
Object.getPrototypeOf
method like:
var person2 = new Person("Hussey");
var personProto = Object.getPrototypeOf(person1);
- Remember from the earlier discussion every function’s prototype has “
constructor
” property which points back to the function itself, and also we can access any object’s prototype’s property directly from object, utilizing these two facts we can access object’s prototype like:
person2.constructor.prototype
Creating Custom Inheritance Chain
Using Objects
This is a pretty straight forward way of creating the inheritance, let's create two objects x
and y
using object literals, and make x
parent of y
using Object.setPortotypeOf
method, as shown in the code below:
var x = { name: "Mike" };
var y = { age: 27 };
Object.setPrototypeOf(y, x);
That's all that is needed to create working inheritance from one object to another. Here object y
is derived from object x
.
Using Constructor Functions
Constructor functions are the normal JavaScript functions written in a certain way. Constructor functions are called using new
keyword. When we call a constructor function using new
, a new
object is created and that object is passed to the function as its context (this
). We can access any function's context using this
keyword, inside function's body.
In object orientated languages like C#, to create inheritance, a class (blueprint of an object) is derived from another class as opposed to the case we have seen in an earlier section where one object is derived from another object. We can mimic the similar classical inheritance in JavaScript using constructor functions. Let's see how.
Let's take the classic example of Employee
and Manager
inheritance. Here Employee
is parent and Manager
is child. We will write a very simple constructor function which represents the blueprint of Employee
object as shown below:
var Employee = function (organization) {
this.organization = organization;
}
Employee.prototype.getOrganization = function () {
console.log(this.organization);
}
Next, let's create Manager
constructor function, keeping in mind that it will be derived from Employee
, we will pass Employee
constructor function and its parameters as parameters of Manager
function as shown below:
var Manager = function (department, parentArg1, parentFn) {
this.department = department;
parentFn.call(this, parentArg1);
}
Manager.prototype.getDepartment = function () {
console.log(this.department);
}
In the next step, we need to establish the prototypal relation between Employee
and Manager
functions. Based on our understanding from earlier discussion, we know that we need to set internal link (__proto__
) from child function's prototype to parent functions prototype, let's write a helper method to do exactly that, as shown below:
function CreateInheritance(child, parent) {
for (var p in parent) {
if (parent.hasOwnProperty(p)) {
child[p] = parent[p];
}
}
var tempProto = function () { this.constructor = child; };
tempProto.prototype = parent.prototype;
child.prototype = new tempProto();
}
In the next step, let's use this utility function to actually create the relation and create an instance of Manager
:
CreateInheritance(Manager, Employee);
var mgr = new Manager("HR", "A WonderFull Company", Employee);
Now mgr
object inherits properties and behavior from the Employee
and Manager
both and you can access those as if they belong to the object itself.
Conclusion
As you can see, it's not very intuitive and seems to be quite a lot of work to make classical inheritance work in JavaScript, but it's certainly possible. Also ECMASCRIPT6 specifications does introduce concept of class in JavaScript however it's just a syntactic sugar and the internal working still remains the same. JavaScript's support of prototypal inheritance is one of the greatest features of it, and it certainly helps to know how exactly it works.