JavaScript Prototypal Inheritance and What ES6 Classes Have to Say About It

Many people come to JavaScript from other object-oriented programming languages such as Java or C++ and are confused as heck. “Where are the classes?” Well JavaScript doesn’t have classes. Rather, JavaScript uses prototypal inheritance to create something similar to classes. Though it is somewhat similar, it’s still quite different and takes a lot of work to understand. That’s the purpose of ES6 Classes.

I recently went over how objects and prototypal inheritance works in JavaScript, so I won’t go into too much detail about it here, but I will point out a bunch of the caveats of the way things are done in JavaScript today.

Current Prototypal Inheritance

Prototypal inheritance isn’t terribly difficult to get started using for simple things, but it gets increasingly difficult (and difficult to understand) when you try to move beyond simple. Looking at the example below (courtesy of Nicholas Zakas because I was too lazy to write my own simple code), when creating the Animal type, you see some oddness, but once you get over that, it’s not difficult. For instance, to create the constructor, we just make a function name Animal. That’s odd, but you get over it and it’s not much of a problem. The only real problem here is that unless everyone follows conventions correctly, it’s difficult to know when someone is just writing a function or if they’re writing a constructor. Conventions in naming help, though.

Anyway, moving on, we see how to add a method to Animal that will be available to all of its instances. Unless you’re quite familiar with JavaScript, the prototype keyword might seem a bit foreign to you, but once again, as soon as you get used to using it, it’s not much of a hurdle. The only thing wrong is readability, as usual, but any seasoned JavaScript developer will recognize it.

1
2
3
4
5
6
7
function Animal(name) {
this.name = name;
}

Animal.prototype.sayName = function() {
console.log(this.name);
};

Now we’re going to get to the troublesome area. In the code below, we’re going to create a type that inherits from Animal called Dog. Two things stick out to me as “bad”. On line 2, we try to call the “super” constructor, but since there’s no super keyword or anything relatively similar, we need to use a not-so-well-known feature of JavaScript, namely call or apply. While the existence of these two functions has started to become better known, they’re still an advanced feature that beginners are unlikely to know. It definitely took me a while to learn about them. In any case, it isn’t elegant.

The second nuisance comes from trying to establish the inheritance, which is done with this code below: Dog.prototype = new Animal(null);. Even now, this code doesn’t make a whole lot of sense to me. I understand what’s going on, but creating an instance of a type so that you can inherit from it doesn’t make sense. Also a potential bug could show up if the Animal constructor does anything besides initialize internal properties, such as DOM manipulation. All we’re trying to do is inherit from Animal but to do so an Animal is created and starts changing the page.

1
2
3
4
5
6
7
8
9
function Dog(name) {
Animal.call(this, name);
}

Dog.prototype = new Animal(null);

Dog.prototype.bark = function() {
console.log("Woof!");
};

Because of these apparent problems, many libraries created their own way of handling this inheritance that simplifies it. There is nothing inherently wrong with the prototypal inheritance model. The problems come from the work required to do it and the misunderstanding that can come from its syntax.

Another Way

JavaScript is a functional programming language (though not only functional), which is part of the reason this has been so difficult up to this point. There’s another way to do inheritance without prototypes that plays more toward JavaScript’s functional nature that relies entirely on object literals and functions to do all of the work. It’s a very interesting alternative, but it pulls even further away from what Java and C++ programmers are used to. If you’re interested, Toby Ho has a great article explaining JavaScript OO without constructors.

The ES6 Way

In ECMAScript 6, we’ll see the introduction of “classes”. Many, many people argue that they are unnecessary, and technically they are. ES6 classes aren’t even classes; they are syntactic sugar that eases our development. That’s all. Classes aren’t an entirely new construct in JavaScript, they are just a new way of saying the exact same thing, except it makes more sense and is simpler to use. Take a look at the following code that rewrites the previous example using ES6 classes:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Animal {
constructor(name) {
this.name = name;
}

sayName() {
console.log(this.name);
}
}

class Dog extends Animal {
constructor(name) {
super(name);
}

bark() {
console.log("Woof!");
}
}

If you came from a background with a classical OO language, wouldn’t this make perfect sense to you? It’s clear, concise, and simple. You get exactly what you think you’re getting. Also, though the syntax is new, there is actually nothing new going on here. It is still doing the same thing as before, just with cleaner code. There’s still prototype chaining, methods are still added to prototypes, you can still manipulate it the same way you did with the old syntax, but you don’t have to anymore.

Conclusion

Do we need to have classes in JavaScript? No, but they definitely clean up the way we define types and do inheritance in JavaScript, which can never be a bad thing. It also helps developers coming from other languages learn about JavaScript a little more easily. The only problem with everything I’ve seen with ES6 is that there won’t be a decent amount of browsers compatible with it for quite some time. But that’s where things like TypeScript come in.

Author: Joe Zimmerman

Author: Joe Zimmerman Joe Zimmerman has been doing web development ever since he found an HTML book on his dad's shelf when he was 12. Since then, JavaScript has grown in popularity and he has become passionate about it. He also loves to teach others though his blog and other popular blogs. When he's not writing code, he's spending time with his wife and children and leading them in God's Word.