Creating classes

Classes are the basic building blocks of many object-oriented systems. JavaScript 1.x (a.k.a. ECMAScript 3) does not support classes natively, although it has prototype objects and constructor functions that look a lot like classes in terms of syntax. Creating class-based programs in JavaScript can be cumbersome, but JS.Class makes it easier.

To make a class, you just ask for a new JS.Class(), and list the names of the methods the class has as regular JavaScript functions.

var Animal = new JS.Class({
    initialize: function(name) {
        this.name = name;
    },

    speak: function(things) {
        return 'My name is ' + this.name + ' and I like ' + things;
    }
});

Classes are expected to have an initialize() method, though this is not essential if no parameters are used to construct instances. The initialize() method is called when you make an instance of the class, and is passed the parameters used to instantiate the new object.

var nemo = new Animal('Nemo');    // nemo.name == "Nemo" 

nemo.speak('swimming')
// -> "My name is Nemo and I like swimming"

Inheriting from a parent class

Let’s say we want to model a more specific kind of animal. We can create a class Dog as follows:

var Dog = new JS.Class(Animal, {
    speak: function(stuff) {
        return this.callSuper().toUpperCase() + '!';
    },

    huntForBones: function(garden) {
        // ...
    }
});

Dog does not need its own initialize() method as it inherits one from Animal. However, it chooses to override the speak() method with its own version.

Now we come to a special method generated by JS.Class, called callSuper(). This method gets created dynamically inside method calls and allows you to access the current method in the parent class. Similar to Ruby, you don’t have to pass any arguments to callSuper(), thus avoiding repetition. The arguments given to the current method are automatically passed by callSuper() up to the parent method.

var rex = new Dog('Rex');
rex.speak('barking')
// -> "MY NAME IS REX AND I LIKE BARKING!"

callSuper() is not accessible from outside the object:

rex.callSuper();
// -> rex.callSuper is not a function

You can pass arguments to callSuper() to override the ones passed in automatically, e.g.:

var Dog = new JS.Class(Animal, {
    speak: function(stuff) {
        stuff = stuff.replace(/[aeiou]/ig, '_');
        return this.callSuper(stuff).toUpperCase() + '!';
    }
});

var rex = new Dog('rex');
rex.speak('something')
// -> "MY NAME IS REX AND I LIKE S_M_TH_NG!"

When overriding arguments you should note that callSuper() always passes all the the current method’s arguments, minus the specifically overridden ones. So if you have a method that takes arguments A, B, C, D, and E and inside that method you call

this.callSuper('one', 'two')

then the code that actually runs is

this.callSuper('one', 'two', C, D, E)

Ruby’s inheritance system is more powerful than simply calling methods in parent classes. For more information on how it works, refer to the inheritance article.