Forwardable

What was it the Gang of Four said? Prefer delegation. Delegation is the act of getting the receiver of a method call to respond by simply passing that call along to some other object. Forwardable, a port of Ruby’s Forwardable module, allows you to easily define instance methods that do just that.

// In the browser
JS.require('JS.Forwardable', function(Forwardable) { ... });

// In CommonJS
var Forwardable = require('jsclass/src/forward').Forwardable;

Let’s say you have a class that wraps a collection of objects, which it stores as an array in one of its instance properties. You might implement some methods for manipulating the array through the class’ own interface:

var RecordCollection = new Class({
    initialize: function() {
        this.records = [];
    },
    push: function(record) {
        return this.records.push(record);
    },
    shift: function() {
       return this.records.shift();
    }
});

Instead, you can extend the class with Forwardable, then use defineDelegators() to create the methods. defineDelegators takes the name of the instance property to delegate calls to as the first argument, and the names of the delegated methods as the other arguments:

var RecordCollection = new Class({
    extend: Forwardable,

    initialize: function() {
        this.records = [];
    }
});
RecordCollection.defineDelegators('records', 'push', 'shift');

var recs = new RecordCollection();
recs.push('The White Stripes - Icky Thump');
recs.push('Battles - Mirrored');

recs.shift()    // -> "The White Stripes - Icky Thump"

If you need to define extra class methods, you need to change the notation slightly:

var RecordCollection = new Class({
    extend: [Forwardable, {
        // class methods go here
    }],

    initialize: function() {
        this.records = [];
    }
});

If you want to give the delegating method a different name, use the defineDelegator() (singular) method instead:

// Add an instance method called 'add' that calls records.push
RecordCollection.defineDelegator('records', 'push', 'add');