Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / Javascript

Prototypal Inheritance with Javascript

4.89/5 (23 votes)
8 Jul 2015CPOL5 min read 28.8K  
Prototypal Inheritance with Javascript

Introduction

I have worked with JavaScript for quite a while now, and for the most part have found it quite straight-forward to use. Most recently, I have been using it with frameworks including React.js and Node.js. As a web developer, JavaScript is part of your toolkit, and working with it is absolutely necessary.

My background is in classical object-oriented languages such as C++ and C#, and I use JavaScript for web development. So for this reason, there were a few areas of JavaScript that caught me out as it works differently to most other languages. I'll hopefully cover those other areas in future articles.

For the purposes of this article I want to cover JavaScript's implementation of object-orientation, and specifically how it implements inheritance.

Background

This article assumes that the reader is familiar with JavaScript. Although the concepts described here apply equally well to all prototypal languages, for the purposes of this article, I will specifically use JavaScript for all explanations and examples.

Most readers will be familiar with classical inheritance through languages such as C++, Java, C# etc. This can create a certain level of confusion when trying to comprehend inheritance in JavaScript which uses what is known as prototypal inheritance. JavaScript is not the only language to implement inheritance using this technique. Other languages include Self, Lua and NewtonScript to name a few.

In classical object-oriented languages you create classes (types) based upon abstractions. We then assign properties and behaviours to those classes. These classes are instantiated in our code to perform various actions and tasks. For example, you may define an Order class with the behavior of returnng a total order amount. In your application you create instances of these Order classes when necessary and invoke their behaviour, such as invoking the behaviour of returning the order total for a specific order.

Objects in JavaScript

Objects are an important primitive within JavaScript. The language is built from them. Whereas in classic object-oriented languages which are built from classes, JavaScript is built from objects. Therefore in JavaScript you can create a new instance of an object as follows.

JavaScript
myObject = new Object();

You can alternatively create the same object using this syntax.

JavaScript
var myObject = {};

This syntax uses object literal syntax. In JavaScript an object is essentially a collection of key-value pairs as in the following example.

JavaScript
myObject = {"Firstname": "Fred",  "LastName": "Smith" };

As can be seen from this object literal notation, this is where the JSON format comes from. JSON is essentially JavaScript object literals without any behaviour (methods).

As JavaScript is a functional language (where functions are first-class citizens) then you can also create objects using functions as in the following example.

JavaScript
function myObject(){}
var myObject = new myObject();

So that's how you create objects in JavaScript. Let's now move on to inheritance.

Inheritance with JavaScript

All fairly straight-forward so far. However, this is not how JavaScript works. It is a class-free, object-oriented language. There is no concept of a class in Javasdcript (or any of the other prototypal languages). Although certain texts may indicate that JavaScript is able to implement classical inheritance, it does not. This is simply syntactic sugar to give the illusion to classical developers that they can implement classical inheritance within JavaScript. The bottom line is that all inheritance is ultimately achieved using prototypal inheritance in JavaScript. This is because.

  • JavaScript is class-free (all classical object-oriented languages rely on the fundamental concept of the class)
  • All inheritance is ultimately achieved via the prototype chain (whether directly or indirectly using syntactic sugar)

Classical inheritance is simulated in JavaScript.

What is prototypal inheritance?

Objects within JavaScript contain an internal object property called prototype.

JavaScript
Object.prototype

The prototype object is the object from which the current object is based i.e. it is the protptype to the current object. To use the language from classical object-orientation, the prototype is the base class or ancestor from which the current object was created. All the methods and properties found on the current object can also be found on its prototype. This prototype object in turn, also contains a prototype object containing the object from which it was created. This chain (called the prototype chain) goes all the way up until we eventually get to the root Object. At this point we can go no further as we have reached the top of the prototype chain.

Let's start with an object called o.

JavaScript
var o;

Our object o contains a property called prototype. This object is the object from which o was created (or from which o was derived to use classical terminology).

JavaScript
var o = new Object()
console.log("typeof Object: " + typeof o); //outputs object
var p = o.prototype;
console.log("typeof o.prototype: " + typeof p); //outputs undefined 

We can keep doing this until we eventually reach the top of the prototype chain.

Inheritance is achieved in JavaScript by two key concepts.

  • Traversing the prototype chain - If JavaScript cannot find the property / method specified then it will look to the object's prototype. If it doesn't find it there, it will look through that object's prototype. It will keep looking at each object's prototype for the specified property / method until it finds it or gets to the top of the prototype chain.
  • The prototype object can be shared amongst different objects. Different objects can all share the same prototype object and can therefore share the same methods and properties.

How do you implement prototypal inheritance?

Now that we understand the underlying concepts of how inheritance is achieved in JavaScript, let's look at a simple example. Here we define an object called Vehicle. We then add a property to the Vehicle object - called make - and add a function that returns this property.

JavaScript
//Defining and instantiating an object called Vehicle using a function
function Vehicle() {}
var vehicle = new Vehicle();

//Adding properties to the Vehicle object. We can either add these as
//instance methods / properties, or to the Vehicle prototype so all 
//Vehicles can inherit them.

//adding an instance property 
function Vehicle(make) {
    // Instance properties can be set on each instance of the class
    this.make = make;
}

//Adding the property to the prototype ensures that all instances 
//share the property
Vehicle.prototype.Make = function() {
    console.log("My make is " + this.make);
};

var vehicle = new Vehicle('Vehicle');
vehicle.Make(); // My make is Vehicle

All well and good so far. Let's extend the Vehicle object by creating a Car class.

JavaScript
function Car(make){
	Vehicle.call(this, make);
}

Car.prototype = new Vehicle();
var car = new Car("Car");
car.Make();

What we're doing is assigning the Vehicle object to the Car's prototype. This allows the Car object to inherit all the methods and properties from Vehicle. We use the JavaScript method call() to achieve this. What this does is allow us to invoke a function and specify the context in which it is to be executed - hence why we pass in the this object. We know that Car has inherited the properties from Vehicle because we have invoked the Make() method that was only defined on our Vehicle object.

Summary

This method of inheritance is probably more difficult to comprehend to a developer coming from a classical object-oriented background. I know that it took me a while to fully grasp what was going on. If you work with JavaScript, then it's important that you understand how JavaScript implements inheritance, and hopefully this article has given a good overview. Feel free to leave a comment if you would like me to further elaborate on anything within this article.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)