Starbeamrainbowlabs

Stardust
Blog

ES6 Features 13: Classes

Almost a year ago I finished a series on the new features of Ecmascript 6, the next version of Javascript. At the time there were one or two features remaining that I hadn't covered, but I didn't feel that today's browsers supported them well enough for me to write a blog post on them. Today, however, that has changed, for classes at least. In this blog post I'll explain by example how classes work in ES6.

Originally, I was against the idea of having classes in javascript. After using them for a while, I've decided to change my mind. They can bring organisation to an otherwise rather cluttered project, especially since the modules syntax hasn't yet landed.

If you've you're familiar C♯, then ES6 classes will feel a little bit familiar. Here's a simple example:


"use strict";
class Bicycle
{
    constructor(inPosition, inColour)
    {
        this.pos = inPosition;
        this.colour = inColour;
        this.wheelCount = 2;
        this.setup();
    }

    setup()
    {

    }

    update(dt)
    {
    }

    render(context)
    {
        // Do rendering stuff
    }
}

Very familiar (I hope). Classes in ES6 are defined using the class Tree { } syntax, with everything belonging to that class inside a set of curly braces, just like in C♯. Because javascript isn't a typesafe language, method declarations look a bit different. Essentially they are the same as a C♯ method declaration, just with the type names taken out.

The "use strict"; at the top is important - today's browsers don't let you use classes without it. I'll omit it in later examples for sake of simplicity, but you'll always need to remember to include it when using ES6 classes.

The constructor() method is, as you've probably guessed, the constructor of your class. Strange way of doing things, I know, but that's how it's declared. Note also that all variable initialisation is done in the constructor and not in the class body. Apparently class definitions are supposed to define an object's capabilities and not its members.

Calling a method from inside is an ES6 is easy too (see highlighted line #8), but it's important to understand what the this variable is in this context first (I could write a whole separate blog post about this). this is a special variable in javascript that holds the current context. In the case of an ES6 class, it holds the current instance of the current class. This is identical to C♯, but the difference is that you'd normally never need to use this in C♯ and it's required in ES6 - for both method access and variable access.

class Tree
{
    grow(dt, rate)
    {
        this.classMethodA(4, dt, this.someVariable);
    }

    // ...
}

White noise

Update: It turns out that ES6 does indeed support static methods (but not variables I don't think) natively via the static keyword. Here's an example:


class Tree
{
    constructor()
    {
        this.something = Tree.doComplicatedStuff();
        this.somethingElse = this.constructor.doComplicatedStuff();
    }

    static doComplicatedStuff()
    {
        // ...!
    }
}

Native static methods can be called in two ways (highlighted above). One is practically the same as the C♯ way of doing things, and the other is useful if for whatever reason you don't have the name of your own class handy.

Original sectional text

You can define static variables and methods too, although it's a little bit of a hack. Imagine I have this class:

class NoiseGenerator
{
    constructor()
    {
        // ...!
    }

    GetNoise(amount)
    {
        // ...!
    }
}
Let's pretend that we want all our noise generated with our class to use the same seedable random number generator. How about rand = new MyPRNG();? Or window.rand = new MyPRNG();? Or even this.rand = new MyPRNG()? Unfortunately, all of these methods have at least one problem with them (if you know what's wrong with them, comment down below!). Don't despair though, because we can exploit the fact that classes themselves are objects - and aren't read-only. With this knowledge, we can do something like this:

NoiseGenerator.rand = new MyPRNG(someSeed);
Remember to put the above _after_ the class definition - ES6 classes are a little bit like C++ classes in that they don't exist until the interpreter has executed them (unlike regular old functions). Then in the body of a method, you can access it with something like `NoiseGenerator.rand.nextInt(0, 10);`.

Too many classes

ES6 classes do infact support inheritance under the guise of sub classing. A good example is worth a thousand words I think:

class Vehicle
{
    constructor()
    {
        // ...
    }

    move()
    {
        console.log("Moving vehicle...");
    }

    start() { console.log("Starting..."); }
    stop() { console.log("Stopping."); }
}

class Train extends Vehicle
{
    move()
    {
        super.move();
        console.log("Moving train...");
    }
}

As demonstrated in the example above, classes can inherit from one another with the extends keyword instead of C♯'s colon. The super word replaces the functionality of C♯'s base keyword too. Other than that, there really isn't a lot more to say about inheritance in ES6 besides the fact that almost everything not described works as you'd expect it to in C♯.

That concludes my whirlwind tour of classes in ES6. If I explained in detail every little feature, you'd be here all week reading about it (and I'd be here for the better part of a month writing this post!). ES6 classes also support getters and setters, overriding the default constructor, and more.

Sources and further reading

Tag Cloud

3d 3d printing account algorithms android announcement architecture archives arduino artificial intelligence artix assembly async audio automation backups bash batch blender blog bookmarklet booting bug hunting c sharp c++ challenge chrome os cluster code codepen coding conundrums coding conundrums evolved command line compilers compiling compression conference conferences containerisation css dailyprogrammer data analysis debugging defining ai demystification distributed computing dns docker documentation downtime electronics email embedded systems encryption es6 features ethics event experiment external first impressions freeside future game github github gist gitlab graphics guide hardware hardware meetup holiday holidays html html5 html5 canvas infrastructure interfaces internet interoperability io.js jabber jam javascript js bin labs latex learning library linux lora low level lua maintenance manjaro minetest network networking nibriboard node.js open source operating systems optimisation outreach own your code pepperminty wiki performance phd photos php pixelbot portable privacy problem solving programming problems project projects prolog protocol protocols pseudo 3d python reddit redis reference release releases rendering research resource review rust searching secrets security series list server software sorting source code control statistics storage svg systemquery talks technical terminal textures thoughts three thing game three.js tool tutorial twitter ubuntu university update updates upgrade version control virtual reality virtualisation visual web website windows windows 10 worldeditadditions xmpp xslt

Archive

Art by Mythdael