Class methods

In Ruby, modules and classes are just another type of object; they are objects that are responsible for storing methods and making new objects. Class methods are methods attached to (and called on) an individual class object, rather than its instances. They are really just a special case of singleton methods. To add class methods when defining a class, wrap them up in an extend block:

var User = new JS.Class({
    extend: {
        find: function(id) {
            // Return a User with id
        },
        create: function(name) {
            return new this(name);
        }
    },
    initialize: function(name) {
        this.username = name;
    }
});

We could equally add the methods after the class was created:

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

User.extend({
    find: function(id) {
        // Return a User with id
    },
    create: function(name) {
        return new this(name);
    }
});

These two syntaxes apply equally to creating and extending Modules. Within a class method, the keyword this refers to the class itself – see the User.create() method:

var james = User.create('James');
james.username    // -> 'James'
james.klass       // -> User

When you create a subclass, it will inherit any class methods of its parent, and you can use callSuper() too:

var LoudUser = new JS.Class(User, {
    extend: {
        create: function(name) {
            return this.callSuper(name.toUpperCase());
        }
    }
});

var me = LoudUser.create('James');
me.username   // -> 'JAMES'
me.klass      // -> LoudUser

var you = LoudUser.find(24)   // inherited from User

Note how this, even in callSuper methods, always refers to the same thing as in the original method call. We get back a LoudUser, not a User.

Note that class methods are not the same as Java’s static methods. If you want to call a class method from an instance of the class, you need to get a reference to the class through the object’s klass property.

User.define('copy', function() {
    return this.klass.create(this.username);
});