Skip to content

Kanishkar J

Javascript Prototypal Inheritance

Javascript3 min read

Inheritance enables objects to take properties from other objects. It is a concept of OOP, it helps developers write simpler and more understandable code. Unlike other languages, javascript takes a different approach to inheritance. It achieves inheritance via a property called object prototypes.

The Prototype Object

Consider a case where you make multiple objects from a constructor, now each object will have its own copy of methods, hence loading the memory. This is where prototype comes into the picture. Every constructor function has a property called prototype. A Prototype is also a javascript object and every instance of the object created references the same prototype object. Every time a constructor is called with the new keyword, It creates a new instance of the object and has a secret link to the prototype defined for the object. This link allows access to the properties defined in the prototype object.

1 jhb8eHrGr7J8 nYsnu9wUQ

Now as we can see the object is linked to the prototype object, and now the prototype object could be linked to another prototype object hence leading to a prototype chain.

So when we call a method or a property from an object, the javascript engine first searches for it in the object definition. And if not available there, it searches for it in an object a step up in the chain and it continues to go up until it finds the property. At the end of every chain is the Object() object. So if the engine reaches there and still fails to find the property, then it returns undefined. Take a look at how prototypes are used in javascript :

1function person(name, age, gender) {
2 this.name = name;
3 this.age = age;
4 this.gender = gender;
5}
6
7person.prototype.speak = function() {
8 console.log(`Hi! I am ${this.name}.`);
9}
10
11person.prototype.listen = function(data) {
12 console.log(`I heard that ${data}.`);
13}
14
15var p = new person("Henry",20,'M');
16
17p.speak(); // prints "Hi! I am Henry." to the console.
18p.listen("I'm Henry");// prints "I heard that I'm Henry." to the console.

Prototypal inheritance

As I said earlier javascript implements inheritance via prototypes. So what we basically do is assign the prototype of the child object as the parent object. Take a look at the code snippet below :

1function Parent() {}
2
3Parent.prototype.fn = function() {
4 console.log("Hi! Im Parent");
5}
6
7function Child1(prop) {
8 this.prop = prop;
9}
10
11function Child2(prop) {
12 this.prop = prop;
13}
14
15Child1.prototype = new Parent();
16Child2.prototype = new Parent();
17
18var ch = new Child1(4);
19ch.fn(); // Hi! Im Parent

Child1 and Child2 have their protoype object set to a Parent object. Hence every instance of Child1 or Child2 will be able to access properties from the Parent Object (line no. 19).

Calling the constructor of the parent function

There are cases where we would want to instantiate the parent object via the constructor of the child object. This can be achieved by Parent.call(this, prop) , take a look at the following code snippet :

1function Parent(parentProp) {
2 this.parentProp = parentProp;
3 this.pEcho = function() {
4 console.log(`Hi! I am ${this.parentProp}.`)
5 }
6}
7
8function Child(prop,parentProp) {
9 // Inherits properties from the parent
10 Parent.call(this,parentProp);
11
12 this.prop = prop;
13 this.cEcho = function() {
14 console.log(`Hi! I am ${this.prop}.`)
15 }
16}
17
18var ch = new Child("child","parent");
19ch.pEcho(); // prints "Hi! I am parent." to the console
20ch.cEcho(); // prints "Hi! I am child." to the console

the this in line no. 10 refers to the current object, the calling object. With the call method, you can write a method once and then inherit it in another object, without having to rewrite the method for the child object.

Object.create()

What is wrong with assigning Child’s prototype as parent’s prototype, i.e. Child.prototype = Parent.prototype . The problem is that this gives direct access to the prototype of the parent object. Hence, parent’s prototype can be modified from the child. Wait, that doesn’t sound good does it? Luckily we have a solution to this, Object.create() .

The Object.create() method creates a new object, using an existing object to provide the newly created object’s prototype. Take a look at the example below :

1function Child(prop) {
2 this.prop = prop;
3}
4
5var ch = Object.create(new Child("Hello!"));
6
7console.log(ch.prop); // prints "Hello!" to the console.

hasOwnProperty() , getPrototypeOf(), And isPrototypeOf()

The hasOwnProperty() method returns a boolean indicating whether the object has the specified property as its own property (as opposed to inheriting it).

1function Parent() {
2 this.parentProp = 10;
3}
4
5function Child(prop) {
6 this.prop = prop;
7}
8
9Child.prototype = new Parent();
10
11var ch = new Child();
12
13console.log(ch.hasOwnProperty('prop')); // true
14console.log(ch.hasOwnProperty('parentProp')); // false

parentProp is defined in the Parent object while prop is defined in the Child object. Hence when hasOwnProperty() is invoked on the Child object with prop as the parameter it returns true, but when invoked with parentProp as arguments it returns false.

The isPrototypeOf() method checks if an object exists in another object’s prototype chain. It is called from the parent object with the instance of the child object as its parameter.

The Object.getPrototypeOf() method returns the prototype of the specified object.

1function Parent() {}
2
3const obj = Object.create(Parent);
4
5console.log(Object.getPrototypeOf(obj) === Parent); // true

That should help one understand how inheritance is achieved in JavaScript. One may note that from ES6 onward, class as a keyword has been introduced into javascript. Which also supports inheritance out of the box, hence one won’t have to mess with the prototype object. But everything is based off the prototypal chain, and hence all of it is just a syntactical sugar over prototypes.