Javascript’s prototypal inheritance, for a C# developer

You can become a serverless blackbelt. Enrol to my 4-week online workshop Production-Ready Serverless and gain hands-on experience building something from scratch using serverless technologies. At the end of the workshop, you should have a broader view of the challenges you will face as your serverless architecture matures and expands. You should also have a firm grasp on when serverless is a good fit for your system as well as common pitfalls you need to avoid. Sign up now and get 15% discount with the code yanprs15!

The other day I put up a post with some quick bullet points about objects in javascript to help someone from a static, strongly typed language (like C# or Java) background understand javascript’s dynamic and loose type system. One important thing I haven’t talked about yet is the way inheritance work in javascript, which again, is very different from those found in C# or Java.

Most object oriented languages like C# and Java use classes to define types, which are basically blueprints for creating objects, this approach to inheritance is referred to as classical inheritance. Javascript on the other hand, has no classes, instead objects inherit from other objects, this approach is referred to as prototypal inheritance.

Constructor functions

You can use functions, which themselves are objects to act as constructors and provide blueprints for creating objects:

function Person(name, age) {
    // properties
    this.Name = name;
    this.Age = age;

    // methods
    this.sayHello = function () {
        return "Hello, my name is " + this.Name + "!";
    }
}

This creates a new object Person.prototype, which all new Person objects will inherit from. You can then use the new operator to create a new Person object using this constructor:

var person = new Person("John", 10);

The person object inherits all the members (properties and functions) that are defined by the constructor function above, as can be seen in Chrome’s debugger (CTRL+SHIFT+J):

image

Dynamically modifying the prototype

It is possible to make changes to Person.prototype object outside of its constructor function, to add a sayBye function to the Person.prototype object:

Person.prototype.sayBye = function (recipient) {
    return "Good bye, " + recipient + "!";
}

Once defined, this new function will be available on all Person objects, even if they were created prior to the new function:

var goodbyeMsg = person.sayBye("Yan"); // returns "Good bye, Yan!"

Understanding how members are looked up

This is all the code we have written so far:

function Person(name, age) {
    // properties
    this.Name = name;
    this.Age = age;

    // methods
    this.sayHello = function () {
        return "Hello, my name is " + this.Name + "!";
    }
}

var person = new Person("John", 10);

Person.prototype.sayBye = function (recipient) {
    return "Good bye, " + recipient + "!";
};

var goodbyeMsg = person.sayBye("Yan"); // returns "Good bye, Yan!"

If you run the code to the end, you will see the sayBye function we added at the end of the example:

image

It falls under the person object’s __proto__ member rather than on the object itself (as is the case for the constructor defined members – Name, Age and the sayHello function) but it’ll still be accessible directly on the person object.

When accessing a member on an object, Javascript will check in that object first, if the member is not found it will then follows the inheritance chain until either the member is found or it will return undefined if it has exhausted all the objects on the inheritance chain.

In order for javascript to keep track of this chain and figure out where next to look for a member, an internal property __proto__ is used to point to the next object in the chain. Because every object is ultimately inherited from Object, it’ll be at the top of every object’s inheritance chain and the last object you’ll be able to fetch if you continuously invoke the __proto__ member before you get undefined returned:

myObj.__proto__.__proto__….

Extending objects

Normally to extend an object you need to perform a two step process:

1. Invoke the base constructor

function Employee(name, age, salary) {
    // equivalent to calling base(name, age) in C#
    // this invokes the base class's constructor on the current object
    Person.call(this, name, age);

    // new property and method
    this.Salary = salary;
    this.reportSalary = function () {
        return "Hi, my name is " + this.Name + ", my salary is " + this.Salary + ".";
    }
}

As you can see, this invokes the Person constructor function (see above) on the current object, if you try to create a new object using this constructor:

var employee = new Employee("Jane", 20, 12000);

this is what the object looks like:

image

Notice anything missing? What happened to the sayBye function we added to the Person object outside of its constructor?

Well, because the sayBye function is not defined in the Person object’s constructor function and all we’ve done so far is to invoke that function to set up some properties and functions for a new Employee object so of course it won’t include anything that’s dynamically added to the object outside of its constructor function.

2. Set up the inheritance relationship

This second step is simple but crucial, this is how you set up the ‘relationship’ between the Person and Employee objects:

// make Employee inherit from Person
Employee.prototype = new Person();

Doing this tells Javascript to use Person as the prototype for Employee, i.e. prototypal inheritance’s way of saying using Person as superclass to Employee. Now that you’ve done this step, if you try to create a new Employee object now this is what your object looks like:

var employee = new Employee("Jane", 20, 12000);

image

Checking an object’s inheritance chain

You can check if an object appear in another object’s inheritance chain using the isPrototypeOf function. For example, using the Person and Employee constructor functions (remember, they are objects) defined above:

var person = new Person("John", 10);
var employee = new Employee("Jane", 20, 10000);

Employee.prototype.isPrototypeOf(person); // false
Person.prototype.isPrototypeOf(person); // true
Object.prototype.isPrototypeOf(person); // true

Employee.prototype.isPrototypeOf(employee); // true
Person.prototype.isPrototypeOf(employee); // true
Object.prototype.isPrototypeOf(employee); // true

Where the inheritance technique fails

Whilst the method of extending an object above works it does have an implicit requirement for the parent object’s constructor function to allow a parameterless constructor to work, which can be a problem in certain situations.

For instance, if the Person object’s constructor explicitly requires the parameters name and age to be specified:

function Person(name, age) {
    if (!name || !age) {
        throw new Error("A person must have a name and age");
    }

    // properties
    this.Name = name;
    this.Age = age;

    // methods
    this.sayHello = function () {
        return "Hello, my name is " + this.Name + "!";
    }
}

In situations like this, this line will except:

Employee.prototype = new Person(); // Uncaught Error: A person must have a name and age

Other inheritance techniques

Besides the technique I mentioned above, here are two other ways to create object inheritance for your reference.

Douglas Crockford’s initialize technique

In Douglas Crockford’s post here he wrote about a different technique on initializing objects, in his last update in 2008 this is his preferred method:

if (typeof Object.create !== 'function') {
    Object.create = function (o) {
        function F() { }
        F.prototype = o;
        return new F();
    };
}

and to use it, suppose we have already created an Employee object called employee, to create another just like it:

var employee2 = Object.create(employee);

This technique is more about cloning an existing object, employee2 will therefore inherit all of employee‘s current state:

image

MooTools

MooTools is a modular Object-Oriented Javascript framework, it includes a Class constructor function which includes some nice features such as:

  • Extends – allows you to specify a base class which to extend from
  • Implements – allows you to specify one or more classes to adopt properties from (think implementing an interface)

So using MooTools, this is how you can create the Person and Employee classes:

// create a new Person class
var Person = new Class({
    initialize: function (name, age) {
        // properties
        this.Name = name;
        this.Age = age;

        // methods
        this.sayHello = function () {
            return "Hello, my name is " + this.Name + "!";
        }
    }
});

// add the sayBye function to the Person class
Person.implement({
    sayBye: function (recipient) {
        return "Good bye, " + recipient + "!";
    }
});

// create a new Employee class which inherits from the Person class
var Employee = new Class({
    Extends: Person,
    initialize: function (name, age, salary) {
        this.parent(name, age); // calls initialize method of Person class
        this.Salary = salary;

        // new property and method
        this.Salary = salary;
        this.reportSalary = function () {
            return "Hi, my name is " + this.Name + ", my salary is " + this.Salary + ".";
        }
    }
});

var person = new Person("John", 10);
var employee = new Employee("Jane", 20, 12000);

This is how the person and employee objects look in the Chrome Debugger:

image

References:

Douglas Crockford on Prototypal Inheritance

MooTools Class examples

Liked this article? Support me on Patreon and get direct help from me via a private Slack channel or 1-2-1 mentoring.
Subscribe to my newsletter


Hi, I’m Yan. I’m an AWS Serverless Hero and I help companies go faster for less by adopting serverless technologies successfully.

Are you struggling with serverless or need guidance on best practices? Do you want someone to review your architecture and help you avoid costly mistakes down the line? Whatever the case, I’m here to help.

Hire me.


Skill up your serverless game with this hands-on workshop.

My 4-week Production-Ready Serverless online workshop is back!

This course takes you through building a production-ready serverless web application from testing, deployment, security, all the way through to observability. The motivation for this course is to give you hands-on experience building something with serverless technologies while giving you a broader view of the challenges you will face as the architecture matures and expands.

We will start at the basics and give you a firm introduction to Lambda and all the relevant concepts and service features (including the latest announcements in 2020). And then gradually ramping up and cover a wide array of topics such as API security, testing strategies, CI/CD, secret management, and operational best practices for monitoring and troubleshooting.

If you enrol now you can also get 15% OFF with the promo code “yanprs15”.

Enrol now and SAVE 15%.


Check out my new podcast Real-World Serverless where I talk with engineers who are building amazing things with serverless technologies and discuss the real-world use cases and challenges they face. If you’re interested in what people are actually doing with serverless and what it’s really like to be working with serverless day-to-day, then this is the podcast for you.


Check out my new course, Learn you some Lambda best practice for great good! In this course, you will learn best practices for working with AWS Lambda in terms of performance, cost, security, scalability, resilience and observability. We will also cover latest features from re:Invent 2019 such as Provisioned Concurrency and Lambda Destinations. Enrol now and start learning!


Check out my video course, Complete Guide to AWS Step Functions. In this course, we’ll cover everything you need to know to use AWS Step Functions service effectively. There is something for everyone from beginners to more advanced users looking for design patterns and best practices. Enrol now and start learning!