JavaScript: Prototypal Inheritance

May 13th, 2013

In my previous article about JavaScript: Objects, Prototypes and Inheritance I wrote using objects and constructor functions to create object hierarchies in JavaScript. I also over-simplified things a little, to make the whole article a bit more comprehensible.

In the article I stated that JavaScript’s behavior for copying objects is different from other prototype-based programming languages, like Self and Io. And it is. But the article is constrained to JavaScript’s classical object inheritance using the new keyword.

Prototypal Inheritance

JavaScript also supports prototypal inheritance. By this I mean inheritance by copying (or cloning) or objects that is typical for prototype-based languages. In JavaScript this practically means inheriting from any object rather than limiting to Function derivatives.

Furthermore, for prototypal inheritance you won’t need the strange (class-like) prototype of a function. You inherit from any object, much like the first example of inheritance I used in my previous article. To refresh your memory, here it is again.

var Person = {
  introduce: function() {
    return 'Hi, ' + this.name + ' here';
  }
}
var bart = {
  name: 'Bart'
}
bart.__proto__ = Person
bart.introduce()
> 'Hi, Bart here'

By changing the object’s internal prototype (i.e. its parent) to Person it inherits all of its attributes. This is prototypal inheritance.

From its early beginning JavaScript supported classical inheritance (i.e. inheriting from a prototype using the new operator). But as a prototype-based programming language it is somewhat awkward to lack prototypal inheritance. Back in 2006 Douglas Crockford wrote an article about this.

His article manifested itself into the core language as the Object.create function. Taking the above example you can make a copy of Person using this function.

var bart = Object.create(Person)
bart.name = 'Bart'
bart.introduce()

The object is identical to the one in the former example and nearly identical to an object created using a constructor.

Indeed, nearly identical. One difference is that JavaScript keeps track of the constructor function of an object. An object created by classical inheritance has its constructor point to the function that created it, while an object created by prototypal inheritance has its constructor point to the constructor of its parent object.

I.e. the following statements would be true given that Person is a constructor function and that Person is the object from the first example respectively.

new Person().constructor === Person
Object.create(Person).constructor === Object

Browser Support

Browser support for prototypal inheritance is pretty good, meaning that Internet Explorer is last of the major browsers to support it (as of version 10). The Object.create function is part of version 5 of the ECMAScript specification and implemented as of JavaScript 1.8.5.

And if you need to support a browser that runs an earlier JavaScript version you can always monkey patch Object, which obviously is one of the major advantages of using a dynamic language.

Performance

But what about performance? JavaScript has been optimized for years on using the new keyword and constructor functions. How does prototypal inheritance relate to that? There one way really to find that out and that would be by testing it.

So I’ve prepared some performance testing and was somewhat surprised by the (very early) results. Not that overall prototypal inheritance is slower than classical inheritance. Like I said, JavaScript has been optimizing the new keyword for years. What surprised me was that this assumption failed for Firefox. It’s also interesting to see how different browsers relate to others, performance wise.

To get a decent overall view it is of course important to get a wide range of different browsers and operating systems. So please run the performance tests on all your browsers, it only takes a few seconds.

The tests and intermediate results are available at: http://jsperf.com/javascript-classical-versus-prototypal-inheritance

So now what?

I believe that both classical and prototypal inheritance have their place in JavaScript development. If you need the speed (i.e. you create many, many objects) you should probably choose using the new keyword. For most other cases I would at least seriously consider prototypal inheritance.

I also believe that most JavaScript code is written in a strict class-based approach. If you find yourself choosing for classical inheritance just because ‘you are used to that’, start practicing with prototypal inheritance only to learn its benefits.

JavaScript has dynamic types, weak types, and no classes. No matter the inheritance approach you choose this does not change. Don’t attempt to change these rules in your code for you will fail. Value duck typing and prototype objects over type checking and class-like object definitions.