I am a Swedish computer science & media technology student who loves to work with exciting projects that involve Visualization, Software Development, Human Computer Interaction and Education. View full presentation

This blog contains random thoughs and some notes from the development of Continuous — a modern WebGL based math visualization tool to help students learn algebra and calculus. Show archive

emil axelsson

July 15 2013

Classes in JavaScript?

I am right in the middle of the process of rewriting Kalkyl which is the module of Continous responsible for working with symbolic math. Since this module will act as a core part of the application, I find it extremely important that the code that goes into this module is childishly simple to read and understand. JavaScript is a language that allows the programmer to structure applications in a thousand ways. In Java, for example, a file must contain excactly one class – not less, not more. To see what methods that are available on an object, you can simply scroll through the code in the class definition.

In JavaScript, on the other hand, methods and fields can be dynamically added to any object at any time. But, if one were to do this, one would quickly end up with a complete mess. Instead, there are some different patterns that I have seen many programmers use. Some of these patterns are completely different from how a class in Java, or C++ is structured and some are trying to mimic the "classical" approaches.

The Module Pattern

The top hit on Google in a search for "JavaScript module pattern" descibes techniques that involve using closure to keep variables and functions private. To achieve something similar to class inheritance, it is suggested that you loop through the members of another object and add references to these to this. This approach completely ignores the prototypal nature of JavaScript. It breaks the instanceof operator, and I find it very weird to scan a file for loops copying references to methods to figure out who the parent class is.

Assigning a new prototype to the constructor

Another pattern that for example Three.js uses is to first create a constructor function, and then add methods to the prototype. The functions end up being stored on the __proto__ member of the object, which means that calls to this.foo() are delegated to this.__proto__.foo(). The files end up with a more clear list of the methods available, which I like. But things get a bit messy when you want inheritance. To inherit from another "class", you have to create a new instance of that parent class and set the prototype of the subclass' constructor to the instance of the parent class. It's not only difficult to say, it's also difficult to understand.

Quack.js

I borrowed ideas from both these patterns when I wrote Quack.js, which is an extremely lightweight library that lets JavaScript programmers define classes like this:

  var SomeClass = quack.createClass({
    constructor: function (bar) {
      this.foo = bar;
    },

    someMethod: function () {
       ...
    }
  
  });

  var SomeSubclass = quack.createClass(SomeClass, function () {
     someNewMethod: function () {
        ...
     }
  });

I also added Java-style abstract classes and interfaces to Quack. quack.createClass will complain if you try to create a class with abstract metods without declaring it abstract. You can not instanciate abstract classes. I do not perform any type checking to see if methods are called with arguments of correct types, but I still find these features useful. Declaring classes and methods abstract is a very nice way of showing your intentions, and I would say that it makes code more readable.

  var SomeAbstractClass = quack.createAbstractClass({
    constructor: function (bar) {
      this.foo = bar;
    },

    someMethod: new quack.AbstractMethod()
    
  
  });

  var SomeInterface = quack.createInterface([
  
    'someOtherMethod'
  
  ]);


  var SomeSubclass = quack.createClass(SomeClass, [SomeInterface], function () {
     someMethod: function () {
        // add your implementation
     }

     someOtherMethod: function () {
        // add your implementation
     }

  });

You can find the source of Quack.js at Github! Feel free to do anything you want with it.