(Part of the “12 Powerful JavaScript Tips” Series)

Prerequisites:
Understand JavaScript’s “this” With Ease
JavaScript Objects in Detail

Chaining Methods, also known as Cascading, refers to repeatedly calling one method after another on an object, in one continuous line of code. This technique abounds in jQuery and other JavaScript libraries and it is even common in some JavaScript native methods.

[sc:mongodb-book]

Writing code like this:

$("#wrapper").fadeOut().html("Welcome, Sir").fadeIn();

or this:

str.replace("k", "R").toUpperCase().substr(0,4); 

is not just pleasurable and convenient but also succinct and intelligible. It allows us to read code like a sentence, flowing gracefully across the page. It also frees us from the monotonous, blocky structures we usually construct.

We will spend the next 20 minutes learning to create expressive code using this cascading technique. To use cascading, we have to return this (the object we want subsequent methods to operate on) in each method. Let’s quickly learn the details and get back to eating, or watching YouTube videos, or reading Hacker News, or working and browsing, or working and focusing.

Let’s create all of our “chainable” code within an object, along with a local data store. Note that in a real-world app we will likely store the data in a database, but here we are just saving it in a variable.


 // The data store:
var usersData = [
    {firstName: "tommy", lastName: "MalCom", email: "test@test.com", id: 102},
    {firstName: "Peter", lastName: "breCht", email: "test2@test2.com", id: 103},
    {firstName: "RoHan", lastName: "sahu", email: "test3@test3.com", id: 104}
];


// A quick utility function that does what it says:
function titleCaseName(str) {
    return str.replace(/\w\S*/g, function (txt) {
        return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
    });
}


// Our object with the chainable methods
var userController = {

    currentUser: "",

    findUser: function (userEmail) {
        var arrayLength = usersData.length, i;
        for (i = arrayLength - 1; i >= 0; i--) {
            if (usersData[i].email === userEmail) {
                this.currentUser = usersData[i];
                break;
            }
        }
        return this;
    },

    formatName: function () {
        if (this.currentUser) {
            this.currentUser.fullName = titleCaseName(this.currentUser.firstName) + " " + titleCaseName(this.currentUser.lastName);
        }
        return this;

    },

    createLayout: function () {
        if (this.currentUser) {
            this.currentUser.viewData = "

Member: " + this.currentUser.fullName + "

" + "

ID: " + this.currentUser.id + "

" + "

Email: " + this.currentUser.email + "

"; } return this; }, displayUser: function () { if (!this.currentUser) return; $(".members-wrapper").append(this.currentUser.viewData); } };

With our chainable methods defined, we can now execute our expressive code like this (just like it is done in jQuery):


 userController.findUser("test2@test2.com").formatName()
.createLayout().displayUser();

Here is the result on JSBin:
http://jsbin.com/erewat/1/edit

Why Use Cascading in JavaScript?

  • There is no need to create temporary variables to save each step of the process. For example, without chaining, our code will look like this:

    
        var aUser = userController.findUser("test@test.com");
        var formatUserName =  aUser.formatName();
        var layoutHTML =  formatUserName.createLayout();
        userController.displayUser(layoutHTML);
      
  • Now, every line of code clearly and succinctly expresses what it is doing, particularly when the name of each method is defined using verbs.
  • Our code is more maintainable because we have simple, lean, specialized methods.
  • Overall, one can easily read the “chainable” code, effortlessly type it, and comfortably understand it.

How Does Chaining Methods Work in JavaScript?

When each method returns this, the entire object that called the method is returned. The execution proceeds thus:


 // Use the userController object to execute the findUser method
 userController.findUser("test@testdd.com")

Because we are executing the findUser method on the userController object, and because the findUser method returns “this” (the object that invoked it), the entire userController object is returned and passed to the next method in the chain, since the “this” keyword in findUser holds the value of the object that invoked it.

Therefore, this occurs next:


 userController.formatName();

Similarly, the formatName method returns the userController object, so expectedly, this follows:


 userController.createLayout();

Followed by: