Understanding "Classes" in EcmaScript 6



By now you may have heard the news, EcmaScript(ES) 6 2015 is finalized and JavaScript is going to be propelled into future, satisfying the needs of non-JavaScript developers to easily transition to a language that didn't have "classes". Well, I'm not here to burst your bubble, but that's not happening. What IS happening, is that we are getting nothing more than syntactic sugar over JavaScript prototypal delegation.


Just to be 100% clear, "class oriented" (Java, C#, etc) programming involves object creation through constructors. It is best to think of traditional instantiation as class instantiation which contrasts JavaScript in which objects are instantiated(created and linked). Objects in JavaScript do not stand on their own, they are interlinked.

If you aren't already familiar with the traditional sense of classes and how developers have been butchering JavaScript to re-invent classes, don't worry, we'll cover it shortly.


Traditional Classes

The way in which many of us learned about classes inevitably clouds our judgement and understanding of a non-class based language such as JavaScript. Classes are the blueprint that is used to create objects. Do not confuse classes and objects, especially in JavaScript. In JavaScript you create objects and link them to other objects.


blueprint for classes image rocket

Going back to how classes actually work, once a blueprint for a class has been defined, such as it's methods and properties, it does not change. Objects are exact and distinct copies of the class. Objects are instances of classes and the process used to create objects involves class instantiation. Following? Good, let's cover one very distinct point with classes and instantiated objects:

Changes to one object instance does not influence other instances. Every object is a copy of the class and is completely independent of other instantiated objects

Inheritance, Encapsulation, Polymorphism, and Overriding are all part of traditional class oriented languages. Normally these are represented as the 4 pillars:

  • Abstraction
  • Encapsulation
  • Inheritance
  • Polymoprhism

These concepts should be familiar, but if they're not, here are some resources to help you brush up:

Object Oriented Programming - MSDN
C# Inheritance - MSDN
C# Overriding - MSDN

I don't want to spend the entire post explaining what classes are in C#, that's best saved for MSDN and other resources. I just wanted to give you a brief refresher if you forgot the details.


Assuming Classes exist in JavaScript


never assume anything lol

It's not entirely your fault if you were mislead by the new and instanceof keywords, especially if you heard "JavaScript is getting classes in ES6!". These keywords, which are very similar to other language keywords referring to class instantiation, have a tendency to confuse newer JavaScript developers.

You can coerce a design pattern in JavaScript to simulate classes through [[Prototype]] delegation but at the 10,000 foot view, you are employing a design pattern, not some fundamental language feature.


Mixins

With JavaScript, there is no inherent way to copy objects or parent function behavior, there is only object linking. Remember, you instantiate/create objects in JavaScript, not classes. These objects, that are linked together through the prototype chain. Through extensive effort and through hacky JavaScript code, we can coerce the language via mixins to "simulate" classes.

Many libraries that try to emulate classes have their own implementation of mixins, such as JQuery with $.extend() or angular.extend().

Frankly, the mixin pattern is very brittle and is typically a maintenance nightmare. Mostly because as a design pattern, it is implemented whichever way the developer felt like hand rolling it. What you're doing is setting yourself up for a series of landmines unless you have a deep understanding of how JavaScript works, and if you did, you wouldn't even bother using mixins.

I've already covered, in depth, why you should use TypeScript and transpile down to ES5/ES6, in which you can minimize all of these landmines, but now we should divert our attention to the EcmaScript 6 classes and what facade we actually get.


ES6 Classes


ecmascript 6 logo

As we initially started to talk about ES6 classes, the class keyword is syntactic sugar over the [[Prototype]] delegation that's been in existence in JavaScript for ages.

Classes are nothing but functions with a few caveats. Classes can exist as class expressions and class declarations.

Remember how in another post we discussed the "hoisting" mechanism, which is nothing more than a JavaScript JIT compilation step that stores variable and function declarations?. In regards to function declarations, the function is hoisted. This is not the case with classes, and classes will need to be declared first before they are used.

Well that's neat, we just lost some awesome functionality for syntactic sugar...


Constructors

Only one constructor function exists within a ES6 class. The constructor function allows you to initialize the objects that will be used within the class and can be coupled with the super keyword. Here is an example:


        class Person {
            constructor(height, weight) {
                this.height = height;
                this.weight = weight;
            }

            get shoeSize() {
                return this.determineShowSize()
            }

            determineShowSize() {
                return this.height * this.weight / 100;
            }
         }

         var oleg = new Person(6, 180);
         oleg.shoeSize(); // 10.8
        

Super

The super keyword allows you to call the parent class functions. This is very similar to base() in C#. Here is an example of its usage:

            class Vehicle {
                constructor(make) {
                    this.make = make;
                }

                manufacturedLocation() {
                    console.log("This " + this.make + " was built in the USA");
                }
            }

            class Car extends Vehicle {
                manufacturedLocation() {
                    super.manufacturedLocation();
                    console.log("This Car is awesome!");
                }
            }

            var toyota = new Vehicle("Toyota");
            var camry = new Car("Camry");

            toyota.manufacturedLocation();
            camry.manufacturedLocation();
        

Extending the Parent Class

The extends keyword allows you to "extend" or "inherit" the base class functionality. This is a way to emulate a subclass. Under the hood we are merely delegating via [[Prototype]]. Here is an example:


            class Person {
                constructor(name) {
                    this.name = name;
                }

                greet() {
                    console.log(this.name + " hails you");
                }
            }

            class Knight extends Person {
                greet() {
                    console.log(this.name + " solutes you");
                }
            }

            var oleg = new Person("Oleg");
            oleg.greet(); // "Oleg hails you"

            var sirOleg = new Knight("Sir Oleg");
            sirOleg.greet(); "Sir Oleg solutes you"

        

Gotchas

Earlier we discussed how traditional classes work and how subclasses inherit functionality. In traditional class oriented languages, the subclass has no way of changing the parent class functionality/blueprint. Think of this as your child breaking their leg, your leg will be just fine(clear parent-to-child relationship). But since JavaScript delegates up the [[Prototype]] chain, you can accidentally bork the parent class behavior.

Let's take a look at an example:


    class Person {
        constructor() {
            this.height = 6;
        }
        describe() {
            console.log( "My height is: " + this.height );
        }
    }

    var oleg = new Person();
    oleg.describe(); // "My height is: 6"

    Person.prototype.describe = function() {
        console.log( "My height is: " + (this.height * 10));
    };

    var michael = new Person();
    michael.describe(); // "My height is 60"

    oleg.describe(); // "My height is 60"......LOL
    

lol what bird

That said, let's look at how you can start using ES6 classes today!

Traceur or Babel

You don't have to wait until all browser adopt the ES6 class syntax(although most of the popular browsers already have). You can begin using the syntax today and transpile with either Traceur or BabelJS. Here are links to get you started:


What to ES6 Fiddle?

A great resource to try and learn more of the ES6 syntax is es6fiddle.net. Check them out and start fiddling!

That's it for now. Happy coding!

[Date Edited: 7/8/2016 6:21:16 AM ]

Leave a Comment