Prototypical Inheritance in Javascript
Okay, So there are many resources on the internet explaining the details of this topic. This is my attempt at explaining this concept in the simplest and most straightforward way possible. So let’s get started.
Target Audience : Beginner Javascript developer with some idea about Object Oriented Programming concepts.
Inheritance is a central concept in OOP, which basically means, child objects can inherit certain properties from their parent objects. Since Javascript is an OO language it also supports inheritance. However, it doesn’t have the concept of classes, so its implementation is not class based like in traditional languages but rather prototype based.
Everything is an Object, almost
The following values are primitives in Javascript
- Strings : ‘a’, “hello” …
- Numbers : 1, 1.23 …
- Boolean : true, false
- null
- undefined
All other values are objects (including functions)
Objects are like dynamic bags of properties. These properties can be primitives, arrays, functions or any other type of object for eg.
Every Object has an internal Prototype property which can be referred using its accessor property __proto__. This acts as the parent object.
In the above example, since the employee object has no custom defined parent, it will directly inherit from the top-level Prototype object.
It’s __proto__ property will point to this top-level Prototype object.
Let’s call the top-level Prototype, the Object Prototype.
This is what the Object Prototype looks like :
The Object Prototype is the ancestor of all objects, it doesn’t have a parent of its own, and its __proto__ property points to null.
So in the above example the prototype chain will look like this :
employee -> Object Prototype-> null
Note : While accessing properties of an object, javascript will traverse through the entire prototype chain till it finds the property it is looking for.
List of inbuilt Javascript prototypes :
- Object Prototype : The top level prototype, ancestor of all objects in Javascript. Has own properties like toString, valueOf, hasOwnProperty etc.
Object().__proto__->null
- Function Prototype : All functions in javascript are objects, and their parent is the Function Prototype. Has own properties like bind, call etc.
Function().__proto__->Object().__proto__->null
- Array Prototype : All arrays in javascript inherit from Array Prototype. Has own properties like slice, splice, length etc.
Array().__proto__->Object().__proto__->null
So, with that out of the way let’s look at some ways to instantiate javascript objects with a flavour of inheritance.
This is the simplest way to create objects, but if you want to use inheritance the following methods will be more useful.
Constructor, is any function that happens to be called with the new keyword.
Every function has a prototype property. It is important to note that this is not the same as __proto__
This prototype property is only available for functions. It’s used when instantiating an object using the function as a constructor.
The resultant object will be a child of the prototype, with its __proto__ property pointing to the prototype of the instantiating function.
The following gist will make it clear.
Object.create is another way of instantiating objects, the first parameter passed to it is the prototype or the parent object. This is what the above example will look like using Object.create
Some things to keep in mind
Property shadowing means when the parent and child objects are using the same property, the parent’s property will not be visible in the child object.
This derives from the fact that, while traversing the prototype chain javascript stops as soon as it finds the right property.
In case of inherited functions, “this” will refer to the child object and not the parent object.
To summarise
- Inheritance is achieved in javascript using prototypes.
- Javascript provides some native prototypes like Object Prototype, Function Prototype and Array Prototype.
- The __proto__ accessor property is used to refer to an objects internal prototype property.
- Javascript will traverse through the entire prototype chain till it finds the right property.
- The prototype property of a function is used to set the parent of the object instantiated when using that function as a constructor.
- There are 3 ways to instantiate objects :
Syntax Constructs
Using the new keyword
Object.create
A word of caution
It is important to check the length of prototype chains in your code as long prototype chains can lead to performance problems as javascript has to traverse the entire chain if it doesn’t find the required property.