One of the coolest “models” to emerge from the JavaScript world in recent times is definitely “prototypal chainability” – a made up term coined by me to describe the indescribable model you see being used in libraries such as jQuery. I’m talking about that which enables you to chain separate method calls (of the same prototype) one after another; each call is made on the same instance. It’s like this:
$('#boo').filter(':funny').addClass('funny').css('color', 'red').show(); |
You might just call it “prototypal inheritance” and be done with it, but I would argue that it goes one step further, by making everything “chainable”!
If you wanted to create your own library with a similar style of notation then you’ll be happy to hear that doing so is incredibly easy. Here are the steps involved:
- Create a constructor.
- Wrap it in something pretty (e.g.
$
). - Add methods to the constructor’s prototype.
- Always return an instance of the constructor from each method.
Here’s an example, our “pretty wrapper” is ‘X’:
(function(){ // Create it in a closure so we don't reveal the constructor: // The constructor: function XConstructor( args ) { // Minor point: convert arguments to real array: this.args = Array.prototype.slice.call( args ); return this; } // The wrapper: function X() { return new XConstructor(arguments); } // Add some methods: XConstructor.prototype = { logArguments : function() { console.log( this.args ); // Return the instance: return this; }, addArgument : function( newArg ) { this.args[this.args.length] = newArg; return this; }, removeArgument : function( index ) { this.args.splice( index, 1 ); return this; } }; // Reveal X to the global object. // Window is the global object in most situations: window.X = X; })(); |
And now, we can do something like this:
X('apple', 'orange', 'pear') .logArguments() .addArgument('banana') .addArgument('melon') .removeArgument(3); // Or, without the indentation: X('apple', 'orange', 'pear').logArguments().addArgument('banana').addArgument('melon').removeArgument(3); |
For all intents and purposes, this is how jQuery’s “chainability” works!
Go fourth and create prototypal chains!
Thanks for reading! Please share your thoughts with me on Twitter. Have a great day!
Chaining is a great technique if you like your scripts concise.
Just a small addition; one thing chains can’t do is give you returned data, as the returned object must always be the original instance. One way around this is to allow an optional callback parameter, so your method can return some data about the instance while invoking a new ‘chain’. Admittedly its not pretty and I don’t do it myself, but it works if you really must do everything on one line.
In the context of object creation this is also called builder pattern. Here is an example from Effective Java (2nd Edition):
see http://www.javaspecialists.eu/archive/Issue163.html for more details, they talk about some of the chapters in this book.
I find it irritating to use the terms ‘prototypal’ or ‘inheritence’ though, since neither is really involved in this approach.
To be clear: this doesn’t really have much to do with prototype-based OO or chaining of prototypes in javascript.
It’s just a convention that can be used in any OO language where you ‘return this’ from methods.
Probably best not to name the technique in a way that leads to confusion with javascript’s prototype-chain-based object attribute lookup semantics.
(I suggest ‘method call chaining’. Or yeah, builder pattern.