Prototypal inheritance in JavaScript

Is JavaScript an Object-Oriented Programming language? Does JavaScript support inheritance? Believe it or not, these are some tough questions that stir up endless discussions.

As in W3Schools.org, “JavaScript is THE scripting language of the Web” On Wikipedia, JavaScript is characterized as “a prototype-based scripting language that is dynamic, weakly typed, general purpose programming language and has first-class functions. It is a multi-paradigm language, supporting object-oriented, imperative, and functional programming styles”.

However, form my point of view, if JavaScript supports object-oriented programming style, doesn’t mean that is an object-oriented programming language, at least not in the way that Java/C#/PHP 5+ is! I think that “JavaScript is an object-based language” is more realistic and closer to truth. However, one of the main characteristics of an OOP language is inheritance, which by the way is supported in JavaScript through prototyping.

Let’s see on code how we can achieve inheritance in JavaScript. First of all, let’s consider a “class constructor” called Human which could act as a base class:

function Human() {};

Since Human is a Function object (everything in JS is an object, even the Function!), it can have properties like “prototype”. In this moment, the prototype property of Human has an automated property called “constructor” which points to itself (to Human function).
If you try to debug this line of code with the Developer Tools from Chrome, you will have the following results:

Property ===> Expected result
DEBUG: Human.prototype ===> Human {}
DEBUG: Human.hasOwnProperty(‘prototype’) ===> true
DEBUG: Human.prototype.constructor ===> Human ()
DEBUG: Human.hasOwnProperty(‘constructor’) ===> false
DEBUG: Human.prototype.hasOwnProperty(‘constructor’) ===> true
DEBUG: typeof Human ===> ‘function’
DEBUG: Human instanceof Function ===> true
DEBUG: Object.getPrototypeOf(Human.prototype) ===> Object {}
DEBUG: Object.getPrototypeOf(Human.prototype) === Object.prototype ===> true

When an object is constructed, that object gets an implicit reference to the value of the constructor’s prototype property, which is an object. “Implicit reference” means an internal thing, not some property of the object. The implicit reference is hidden away, but it can be extracted with Object.getPrototypeOf(). E.g. When we write function Human() {}, Human has a new object constructed called prototype which “gets an implicit reference to the value of the constructor’s prototype property (Object.prototype)”. The “constructor’s prototype property” is finally an object (the base of all the things in JavaScript).

Property ===> Expected result
DEBUG: Object.getPrototypeOf(Human.prototype).constructor === Object ===> true
DEBUG: Object.prototype ===> Object {}

Next, consider the following line of code:

Human.prototype = {
  name : 'John'
};

After this line of code, the prototype will become a simple object, and because of poor JavaScript design, the prototype’s constructor property will point to Object (). That’s because the constructor property is no longer part of the Human.prototype, but rather of Object.prototype (if the property isn’t found in the prototype object, it is looked for in the prototype object’s prototype).

Property ===> Expected result
DEBUG: Human.prototype ===> Object { name : ‘John’}
DEBUG: Human.prototype.constructor ===> Object ()
DEBUG: Human.prototype.hasOwnProperty(‘constructor’) ===> false

Human.prototype.color = 'white';
Human.prototype.getName = function() {
  return this.name;
};
Human.prototype.getColor = function() {
  return this.color;
};

After these lines of code, the prototype will become Object { name : ‘John’, color : ‘white’, getName : function() { return this.name }, getColor : function() { return this.color } }
And now for the “object instantiation”:

var h = new Human();

Also the poor design of JavaScript is further reflected when instantiating the object h. That is, the contructor is not taken from Human.prototype, because as previously mentioned, the prototype of Human is a simple object with no automated constructor property and that’s why the constructor is taken from one level up which is from Object.prototype.

Property ===> Expected result
DEBUG: h.constructor ===> Object ()
DEBUG: Object.getPrototypeOf(h) ===> Object {
name : ‘John’,
color : ‘white’,
getName : function() {
return this.name;
},
getColor : function() {
return this.color;
} }
DEBUG: typeof Object.getPrototypeOf(h) ===> ‘object’
DEBUG: typeof h ===> ‘object’

To “patch” JavaScript’s poor design, we will create the constructor property which points to itself (to Human)

Human.prototype.constructor = Human;

Property ===> Expected result
DEBUG: Human.prototype ===> Human {
name : ‘John’,
color : ‘white’,
getName : function() {
return this.name;
}, getColor : function() {
return this.color;
}
}
DEBUG: Human.prototype.constructor ===> Human ()
DEBUG: Human.prototype.hasOwnProperty(‘constructor’) ===> true
DEBUG: h.constructor ===> Human ()
DEBUG: Object.getPrototypeOf(h) ===> Human {
name : ‘John’,
color : ‘white’,
getName : function() {
return this.name;
},
getColor : function() {
return this.color;
}
}

And now for the child class, which in our example will be called SuperHuman:

function SuperHuman(superpower) {
  this.superpower = superpower;
};
 
SuperHuman.prototype = new Human(); // inherit from Human
 
SuperHuman.prototype.getSuperpower = function() {
  return this.superpower;
};
 
var sh = new SuperHuman('laser');
 
SuperHuman.prototype.constructor = SuperHuman;

If you have the curiosity to debug the code and check the state of the properties after each line of code, you will see that SuperHuman will behave in the exact same way as Human did – that’s because SuperHuman inerits from Human and therewith all the design problems that we encountered before.

See ya!