ES6 classes are pretty handy for extensibility

ES6 introduced syntax sugar for something a lot of people were already doing in ES5, namely simulating classical object-oriented inheritance.  That move got some blowback from people who say that prototypal inheritance is better, or classes are terrible.  And it’s true that classes aren’t really a natural part of JavaScript.

We had a scenario recently though where we found that ES6 classes were a good fit.  We were adding the ability to define your own custom elements in jsreports.  These are basically custom components that leverage built-in behavior and add their own logic too.  For example, you can define a checkbox component with a boolean “checked” property that toggles based on a data calculation (this is actually one of the examples we provide, because it’s so simple).

Here are some of the advantages we found when using classes:

  • The ES6 class syntax is concise and easy to read; it’s easy to take a class we provide and pretty easily see where the natural extension points are.  The class structure is a good way for our code to self-document what it is and how it relates to other components.
  • Classes are a good match when the thing you’re modeling already has an “is-a” relationship.  In our case, custom elements are natural subclasses of an abstract Element type that already has many concrete implementations.
  • Having a built-in class syntax allows you to “say what you mean” in the code, instead of piecing together a bunch of functions and prototypes manually.  On top of the human readability advantage already mentioned, this opens the door to better documentation generation and tooling.

But there are some things to watch out for, too:

  • The explosion of subclasses.  In a way, classes provide the perfect trap for programmers who are already tempted to over-abstract things.  The antidote (for us) is to keep class hierarchies shallow and class count low, and tend toward composition where possible.
  • Since this is just sugar, it’s important to have a good understanding of how concepts like statics and visibility work in the underlying JavaScript.  If your experience with classes comes from a language like Java or C#, there are some surprises in store.
  • ES6 doesn’t support interfaces, which would be helpful in our scenario.

Now, not all of our customers are using an ES6 environment yet.  We still provide our pre-built bundles in ES5, but we also ship (to customers) our Babel build chain and ES6 source.

We’re pretty happy with how well it’s worked out so far.

For more on ES6 classes, see https://hacks.mozilla.org/2015/07/es6-in-depth-classes/.

Useful thoughts on API design and classes can be found in Joshua Bloch’s classic presentation “How to Design a Good API and Why It Matters.”