The single most important development on the JavaScript scene recently has been the standardization of classical syntax in ECMAScript 6 (ES6 or ES2015). Of course, this is opinion but the new class syntax really does help if you have been writing JavaScript in a pseudo classical form.

Why Use Classes?

JavaScript already supports objects as first class citizens and you can even skip the new operator entirely. However this route can lead to chaos quite easily.

If you ask me, classes are about code organisation more than anything else. It’s easier to think in terms of: ‘the function accepts a MyClass instance’ than ‘ the function accepts an object returned from calling X function’.

Arguably however, the organisation I’m referring to comes from having types and recognizable interfaces we can refer to.

I think ES6 classes bring us closer to thinking in terms of interfaces rather than strictly passing behaviours around.

Before ES6

In ES5, to simulate classes, we use a combination of constructor functions and prototype objects.

Whenever new is called on a function, the JavaScript engine creates a new object within the function’s body scope and sets the value of this to that object.

The object is given a __proto__ property that is copied from the function’s prototype property and acts as the object’s prototype.

A prototype is a special property on any JavaScript object that is consulted whenever a property request is made that the object can’t fulfil from its own properties (functions on objects are properties as well).

Prototypes are objects and also have their own prototypes.

Think of it as a chain or a reverse tree that we traverse when someone asks us for a value we do not already own, hence prototype chain.

function MyClass() {}

MyClass.prototype.doSomethingSpecial = function () {
   console.log('Not thanks!');
}

If we had added doSomethingSpecial to the MyClass function directly instead of to the prototype, then we would only be able to call that function using MyClass.doSomethingSpecial().

Functions are objects after all and the instances don’t check their constructor function for properties they don’t have.

We have to add the method to MyClass‘s prototype so new instances of MyClass can access it through the prototype chain.

And what about inheritance?

This is where the syntax gets really gruesome:


function MyClass() {
   SomeConstructor.apply(this,  arguments);
}

MyClass.prototype = Object.create(SomeConstructor.prototype);
MyClass.prototype.constructor = MyClass;

In the body of our constructor, we optionally call the constructor function of the SomeConstructor class and bind it to the current scope’s this value (ie: the object we are constructing).

We use Function.prototype.apply for that.

This would be similar to a child class calling the super() keyword in Java.

The next lines run immediately as they are assignments and not function definitions.

We create a new prototype for MyClass, using Object.create.

This new prototype will have its own prototype set to whatever the first argument of Object.create is which in this case is SomeConstructor.prototype.

This has the effect of allowing objects created with MyClass to query SomeConstructor.prototype for properties in addition to SomeConstructor.prototype.prototype and so on.

I like to think of this like smashing an amino acid chain into two parts and connecting one part to another chain and discarding the other.

Before inheritance Before Inheritance

After inheritance

After Inheritance

The last line sets the constructor property of MyClass back to MyClass. I’ve noticed that if you don’t do this, uncaught errors show up as Object #SomeConstructor rather than Object #MyClass which can be misleading.

Now all this gets tiresome quickly, especially if your code base deals with a lot of classes.

It should be mentioned that there are libraries out there that handle these details for you. Node.js has the util.inherit function built in.

Convenient, but it makes code less obvious if you ask me.

Why all this torment?

As far as I can tell, JavaScript was not meant to be used this way. It was after all influenced by Scheme.

If you have ever tried one of the Lisp dialects, they are a joy once you get the paradigms down. I still find it hard to model ‘business-logic’ in them however. I think that takes a lot of time and practice to get right.

Send in the Classes!

The examples from before in ES6 syntax look like this:


//class
class MyClass {

  doSomethingSpecial() {

  }

}

//Inheritance

class MyClass extends SomeConstructor {

   constructor() {
      super()
   }

   doSomethingSpecial() {

   }

}

That’s it. Much less work and certainly easier on the eyes.

I’ve even started writing interfaces in this syntax and using jsdoc to generate useful documentation.

Now Browser support for classes is almost non-existent and it’s the same on the server with Node.js/io.js.

Screen grab from MDN

Class Support

But fear not!

Thanks to excellent transpilers like babel you can use these features with little fuss on both the client and server side.

That is of course if you don’t mind the extra build step.

The new ES6 class syntax may not be for everyone but it certainly has been working for me. Do you tend to use factory methods, adapters and other patterns in your code?

ES6 classes makes that stuff a lot less cumbersome.