JavaScript (ES6) classes

  Read comments... Posted on 11th January 2016, short URL: http://rgraph.net/jscl

Summary
This is a description of JavaScript (ES6) classes - a new alternative to using the existing prototypal way of defining objects.

Introduction

JavaScript 2015 (formerly ES6) has added some syntactic sugar in the way of classes for defining objects (as well as the pre-existing prototypal method). This is more inline with other languages so it will be more familiar to people coming to JavaScript from other languages as well as maintaining backwards compatibility for existing code; so existing code should continue to work side-by-side without requiring any modifications.

You can read about the older prototypal method of defining objects in this article.

JavaScript classes are supported in Chrome 42, Firefox 45, Edge 13 and Safari 9.

An example of the syntax

'use strict'; // You need to be using strict mode

// Use this further down to build a method name
var partialName = 'mp';

// 1. The class definition
class MyClass
{
    // 2. The constructor
    constructor (a, b, c)
    {
        // Add the arguments to the constructor to the object
        this.a = a;
        this.b = b;
        this.c = c;
    }

    // 3. A static method (you don't need to create an instance to use this function)
    static myStatic(a, b, c)
    {
        return a + b + c;
    }
}


// 4. A class which derives from MyClass
class MyOtherClass extends MyClass
{
    constructor (a, b, c, d)
    {
        // Call the parent constructor. Needs to be the first thing
        // in the subclasses constructor
        super(a, b, c);
        
        this.d = d;
    }

    // 5. A getter and setter pair of functions
    get name()
    {
        return this.d;
    }
    
    set name (arg)
    {
        this.d = arg + '666';
    }


    6. A toString() method for when the object is cast to a string.
    toString ()
    {
        return 'My first object!';
    }


    // 7. A computed method name (the method ends up being called dump() )
    ['du + partialName]() {
        console.log(this.a);
        console.log(this.b);
        console.log(this.c);
        console.log(this.d);
    }
}

1. The class definition

This is the definition of the class - just like traditional class definitions. One thing to bear in mind though is that class definitions are not "hoisted". This basically means that, unlike function declarations, you have to define the class before you use it.

Classes can only contain functions - not properties. If you want default property values you'll need to define them in the constructor.

Similarly to how you can use function expressions as well as function declarations, you can also declare classes using expressions like this:

'use strict';

// Define the class
var MyClass = class
// var MyClass = class MyClass // Also possible (with the name)
{
};

// And then use it
var obj = new MyClass();

2. The constructor

The constructor is a special function that is run when you create the object. There can be only one of these methods. If you wish you can refer to the parent classes constructor (if there is one) by using the super keyword.

3. Static methods

You can use the static keyword to define a static method. This is a method that can be called without first creating an instance of the class. Also, when you do create an instance of the class, you can't then call static methods. Static methods are sometimes used for utility functions of classes. Another use might be to implement the OOP Factory design pattern.

4. A class which derives from MyClass

This is a subclass that inherits from the MyClass class. The first thing that this does in its own constructor is call the parent classes constructor using the super() keyword. It then sets the extra variable (which in this case is d) on the object.

The subclass then defines a dump() method which, when called, simply logs the class variables (a, b, c, d) to the console.

5. A getter and setter pair of functions

New to the class object model are getter and setter functions. As the name suggests these allow you to put code behind the setting and getting of properties.

So this means that when you do this:

obj.name = 'Fred';
Your defined setter can run, which might be this:
set name (value)
{
    // The underscore is just a convention.
    this._name = value;
}

This is just syntactic sugar, as you can just access the _name property directly if you wanted to. Though it can be useful.

The get function is similar. You can define just the get function and no setter - but unfortunately this doesn't make the property readonly as someone could just access the underlying property directly.

Also, you can just define the setter and you can just set the property - but again if you wanted to read the value you can just access the underlying property and bypass the getter/setter.

Which combination of setter/getter or no setter/no getter etc can be a little confusing so possibly the best thing to do is define both and just have the setter do nothing if you don't want it to. But! Keep in mind that the underlying property can always be accessed by the user.

6. A toString() method for when the object is cast to a string.

When the object is cast to a string (eg alert(obj); the 'magic' toString() function runs allowing you to define how the object acts. The return value is what is used as the value of the object.

7. A computed method name

Computed method names can be used to build method names out of already existing variables. So if you had a variable that ontained a string and you wanted to name a function the same - then you could do this (assume that the myVar variable contains the string "Print"):

['my' + myVar] ()
{
    // ...
}

And then you could call that function by doing this:

obj.myPrint();

ES5 (ie current JavaScript) has something a little similar to this. If you treat your object as a hash/array and access the function that way:

var obj = {};
obj['myPrint'] = function ()
{
    alert('Hello!');
};

obj['my' + myVar]();

Remember though that doing this will make the myPrint() function a function expression, not a function declaration (ie it's a function thats defined/created at runtime - not compile time.

Conclusion

The new ES6 classes are a more traditional way of defining classes/objects in JavaScript that may be more familiar to you (and therefore more accessible). They don't add anything of great use (yet?) and, certainly in the case of RGraph, they won't be being used any tme soon (because of backwards compatibility concerns). The inability to specify that a property is private is a missed opportunity IMO so if you need these then you may wish to stick to the ES5 method of defining objects.

Share RGraph
X

Comments