As suggested by Johan Bouveng, the first real post here is about Method Chaining. This is the technique jQuery uses for its magic.
To take an example from the jQuery home page:
$("p.neat").addClass("ohmy").show("slow");
This takes all <p> elements with a class name of neat, adds the class ohmy and then slowly animates the appearance of the elements. Equivalent code without chaining could look like this:
var neatos = $("p.neat");
for (var i = 0; i < neatos.length; i++) {
addClass(neatos[i], "ohmy");
show(neatos[i], "slow");
}
neatos = null;
In this example a few advantages of chaining become clear:
- Clear, concise code: this makes it easier for fellow programmers to spot the important bits, such as adding a class name and showing the elements.
- No variables used: the actions on the paragraphs are invoked on the result set of the
p.neatselector - No worries about memory leaks, because there are no references to DOM elements
Disadvantages include more magical code, that quite possibly runs slower that non-chained code. For example, whereas the non-chained code uses one iteration over all paragraphs, the chained code iterates twice. Once for addClass() and once for show(). That said, this slight performance loss usually doesn’t hurt, and if it does, you can always remove the chains.
How does method chaining work? The general principle is that each function call returns an object on which you can call other functions. Many jQuery functions return the object on which they are called themselves:
var neatos = $("p.neat");
neatos === neatos.addClass("ohmy"); // true
Others, like filter(), return a different object, which supports the same methods.
Chaining Ourselves
Let’s play with some method chaining ourselves:
var chain = { // Create a new object
set: function(name, value) {
this[name] = value; // Do stuff here, in this case, set a property
return this; // Return a reference to the object itself.
},
get: function(name) {
return this[name]; // Return the value
}
};
This creates a chain object, which has a get() and a set() method. The set() method lets you set properties on the object, and returns the chain object. get() returns a value.
Now we can run the following:
chain.set("foo", "bar").get("foo"); // "bar"
chain.get("foo"); // "bar"
chain.set("baz", "thud").set("hello", "world").get("hello"); // "world"
chain.get("foo"); // "bar"
chain.get("baz"); // "thud"
chain.get("hello"); // "world"
We can’t run this:
chain.get("foo").get("baz"); // chain.get("foo").get is not a function
chain.get("foo") returns the value, which is not the chain object, and does not have the get() method.
Chaining with Class
Here we have only one chain object. Let’s create a class, so we can create several chainable objects:
function Chain() {};
Chain.prototype.set = function(name, value) {
this[name] = value;
return this;
};
Chain.prototype.get = function(name) {
return this[name];
};
Now we can do this:
var chain = new Chain();
chain.set("foo", "bar").get("foo"); // "bar"
Let’s add a filter() method, which creates a new Chain object:
Chain.prototype.filter = function() {
var result = new Chain();
for (var i = 0; i < arguments.length; i++) {
result.set(arguments[i], this.get(arguments[i]));
}
return result;
};
For example:
var chain = new Chain();
var filtered = chain.set("foo", "bar").set("baz", "thud").set("hello", "world").filter("foo", "baz");
filtered.get("foo"); // "bar"
filtered.get("baz"); // "thud"
filtered.get("hello"); // undefined
Conclusion
This concludes Part One of Method Chaining. We’ve seen why method chaining is so useful, and how it works. In Part Two, we’ll look at dojo.Deferred, which uses Method Chaining in order to, well, chain methods!
Hi Mark! Thanks for this useful post on this magic ninja subject. There are many things and techniques thats really not being teached, or explained. Javascript is expressive and fun and we learn new things every day and as our skill increases we want to play with new stuff. In my case i want to build my own little tiny library, for fun and educational purposes, that i have written myself and only does the basic stuff i do in the DOM on an everyday basis. And of course i would like some chaining magic. This post will come handy, and i cant wait for part #2.