Cory Rylan

My name is , Google Developer Expert, Speaker, Software Developer. Building Design Systems and Web Components.

Follow @coryrylan
JavaScript

JavaScript Prototypal Inheritance

Cory Rylan

-

Updated

The Prototype is a JavaScript object property that gives us inheritance and re-usability in our objects. If you come from a classical Class based language such as Java or C# prototypes can be confusing at first. In this post I am going to cover a simple example where we will create multiple objects and create a inheritance chain between them.

First lets create our first object. JavaScript does not have a formal Class keyword as of the current ES5 version in most browsers. This post will focus on current techniques using ES5 syntax. The upcoming EcmaScript 6 edition will bring the Class keyword with some syntactic sugar for creating and managing objects.

To create objects we use functions to create constructors for our objects. It is the convention to capitalize functions that are object constructors. Any other functions that are not constructors should start lower case.

function Person(name) {
  this.name = name;
}

Here is our new Person constructor. It contains on instance property called 'name'. Now lets create a couple of objects from our constructor.

function Person(name) {
  this.name = name;
}

var bob = new Person('Bob');
var john = new Person('John');

console.log(bob.name); // Outputs 'Bob'
console.log(john.name); // Outputs 'John'

As you can see we have created two new instances of our Person object, Bob and John. Each have their own name property that logs out their respective values. Now lets make our Person class a little more useful by adding a walk method.

function Person(name) {
  this.name = name;
}

Person.prototype.walk = function() {
  console.log(this.name + ' is walking.');
};

var bob = new Person('Bob');
bob.walk(); // Outputs 'Bob is walking.'
var john = new Person('John');
john.walk(); // Outputs 'John is walking.'

Here we add a new method walk to the prototype of our Person object. Every object in JavaScript contains a prototype object. Think of the prototype object as your blueprint for your objects. Anything you attach to the object prototype new instances of that object share the prototype. This prevents the creation of a new walk method from being created with every person object.

A side note it is usually bad practice to alter or extend native JavaScript object prototypes such as Object or Array. Manipulating these object prototypes could result in conflicts with future versions or methods added to these native objects. Exceptions to this practice would be to pollyfill newer JavaScript features for browser support such as Array.Map, Array.ForEach, ect.

Object Inheritance

So what if we want to create a Programmer object that inherits our Person object? First lets make a Programmer constructor.

function Programmer(name) {
  Person.call(this, name);
  this.programmingLanguage = '';
}

So now we have a simple constructor with two properties a name and programmingLanguage. The call statement allows us to set the name property in the context of the Person constructor. This could be roughly equated to a super call in other object oriented languages. So how do we inherit the Person object? We use prototypes.

function Person(name) {
  this.name = name;
}

Person.prototype.walk = function() {
  console.log(this.name + ' is walking.');
};

function Programmer(name) {
  Person.call(this, name);
  this.programmingLanguage = '';
}

Programmer.prototype = Object.create(Person.prototype);
Programmer.prototype.constructor = Programmer;

var cory = new Programmer('Cory');
cory.walk(); // Outputs 'Cory is walking.'

Using Object.create will create a new object from Person.prototype and allows us to set Programmer.prototype to it. Programmer will inherit all the Person properties and methods from the Person constructor and prototype object.

The second part is setting the prototype constructor property. Every object's prototype contains a constructor property that defines what its original constructor was. When you set a object property to inherit another object you must make sure to define your constructor property to reflect the new object you are creating. If this is not set the prototype.constructor property will return the original parent object as this would be incorrect for the child object. So we would set our Programmer object to: Programmer.prototype.constructor = Programmer;.

Now that we have a Programmer object that inherits our Person object lets add a writeCode method so our Programmer is a little more useful.

function Person(name) {
  this.name = name;
}

Person.prototype.walk = function() {
  console.log(this.name + ' is walking.');
};

function Programmer(name) {
  Person.call(this, name);
  this.programmingLanguage = '';
}

Programmer.prototype = Object.create(Person.prototype);
Programmer.prototype.constructor = Programmer;
Programmer.prototype.writeCode = function() {
  console.log(this.name + ' is coding in ' + this.programmingLanguage + '.');
};

var cory = new Programmer('Cory');
cory.programmingLanguage = 'JavaScript';
cory.walk(); // Outputs 'Cory is walking.'
cory.writeCode(); // Outputs 'Cory is coding in JavaScript.'

So now we have created a Programmer object that inherits a Person object. Our Programmer object can now walk from inheriting the Person object but can also writeCode from its own method and programmingLanguage property.

Private Members in Constructors

So what if we wanted private properties on our objects that only the object itself can alter? For example we have a skill level property on our Programmer object that we want to only be increase by one point at a time?

We would like the skillLevel property to incremented by a method increaseSkillLevel that increments the property by one point. We also want to be able to get this value but not be able to set so we would want a getSkillLevel method.

function Programmer(name) {
  var skillLevel = 0;

  Person.call(this, name);
  this.programmingLanguage = '';

  this.getSkillLevel = function() {
    return skillLevel;
  };

  this.increaseSkillLevel = function() {
    skillLevel += 1;
  };
}

Programmer.prototype = Object.create(Person.prototype);
Programmer.prototype.constructor = Programmer;
Programmer.prototype.writeCode = function() {
  console.log(this.name + ' is coding in ' + this.programmingLanguage + '.');
};

var cory = new Programmer('Cory');
cory.programmingLanguage = 'JavaScript';

console.log(cory.getSkillLevel()); // Outputs '0'
cory.skillLevel = 1000;
console.log(cory.getSkillLevel()); // Outputs '0'
cory.increaseSkillLevel();
console.log(cory.getSkillLevel()); // Outputs '1'

As you can see I can now only edit or get the programmer's skill level through the properties exposed by the constructor. This allows private members on our objects. Now there is a downside to this method. Every instance of Programmer will now create a getSkillLevel() and increaseSkillLevel() method. Because these methods are defined in the constructor instead of being defined on our prototype they cannot be shared across all instances of Programmer. This results in a much less efficient object than when the properties are defined on the prototype. This is the only technique to allow private members on your objects that are not Singleton or Module based.

So we have covered how to create custom objects and inheritance chains using prototypes. These techniques will soon be optional with the upcoming ES6 spec and Class syntax. Remember even with the new Class syntax soon on its way, under the hood it is still prototypal inheritance at work. ES6 Class will add syntactic sugar giving our code a cleaner syntax to work with.

Twitter Facebook LinkedIn Email
 

No spam. Short occasional updates on Web Development articles, videos, and new courses in your inbox.

Related Posts

JavaScript

Use JavaScript Date Objects with the HTML5 Date Picker

Learn how to easily use both the native HTML5 datepicker and JavaScript Date objects together.

Read Article
Web Performance

Design System Performance with Clarity Core Web Components

Learn how to build high performance UI and Design Systems on the Web using Clarity Core.

Read Article
Web Components

State of Web Components in 2020

Learn a brief overview on Web Components and the latest tech available to build and distribute components across the Web.

Read Article