What Is Method Chaining?
Method Chaining in Javascript is a design pattern in which we can call methods one after another without assigning the return value of each method to a variable. You can see this pattern being commonly used on strings, arrays and objects in Javascript.
For example, we want to convert an email id to lowercase and remove white spaces if any. To do so we can call first call the toLowerCase()
on string and later call the trim()
method.
let email = "Me@example.com"
let lowerCaseEmail = email.toLowerCase();
let finalEmail = lowerCaseEmail.trim(); // 'me@example.com'
In this example, we use two variables, one to store the return value of toLowerCase()
method in lowerCaseEmail
and other to store the return value of trim()
method in finalEmail
.
However, Javascript allows us to perform the above operation in a single line without the need for creating variables using the method chaining pattern.
email.toLowerCase().trim(); // 'me@example.com'
As you can we are able to call the trim()
method after the toLowerCase()
without a need to create additional variables.
We can take this further by calling another method split()
via @
character.
email.toLowerCase().trim().split('@'); // ['me', 'example.com']
But, how does it work?
Okay, we get it, chaining is cool but how does it work and can we chain any method? To understand this we need to first understand what each method returns. In the above example, we have first used the toLowerCase()
method which returns a string converting it to lower case. Next, trim()
method takes the output of toLowerCase()
which is a string and again returns a string object. So, as long a method returns a string object we can chain a string method to it.
Notice we have also made use of the split()
method which returns an array instead of a string object. Hence, if we try to chain another string method, it will throw an error.
email.toLowerCase().trim().split('@').toUpperCase();
// Uncaught TypeError: email.toLowerCase(...).trim(...).split(...).toUpperCase is not a function
Of course, if you use an array method instead of a string method it will work just fine.
email.toLowerCase().trim().split('@').sort();
// ['example.com', 'me']
With this in mind, let’s create our own methods and apply chaining to them.
"use strict";
let actor = {
firstName: "Mickey",
lastName: "Mouse",
age: 10,
height: '',
weight: '',
eats: [],
setHeight: function(height) {
this.height = height;
return this;
},
setWeight: function(weight) {
this.weight = weight;
return this;
},
food: function(item) {
this.eats.push(item);
return this;
}
};
actor.setHeight(3).setWeight(10).food('Cake').food('Pizza');
/*
OUTPUT:
{firstName: 'Mickey', lastName: 'Mouse', age: 10, height: 3, weight: 10, …}
age: 10
eats: (2) ['Cake', 'Pizza']
firstName: "Mickey"
food: ƒ (item)
height: 3
lastName: "Mouse"
setHeight: ƒ (height)
setWeight: ƒ (weight)
weight: 10
*/
In the above example, we are able to chain methods on object actor
. This is because every method of the object returns the object i.e, it returns this
which is nothing but the object actor
.
actor.setHeight(3).setWeight(10).food('Cake').food('Pizza');
When we call the setHeight()
method, it assigns the height
property and returns this
which is next used by the setWeight
method to assign the weight
which again returns the this
containing the actor object to be used by the next method food()
.