Method Chaining in JavaScript

In programming, a widely accepted best practice is to develop separate functions or methods to manage individual actions. Although it is possible to merge all functionalities into a single method or function, following best practices can enhance the readability and clarity of the code. This is mainly due to the fact that by creating distinct functions for each specific action, the output from one function can serve as the input for another. As a result, this can make understanding the code more challenging, particularly since functions might need to be organized in reverse nesting order. Method chaining presents a viable approach to address this challenge.

What is method chaining?

Method chaining is a coding approach that improves both the clarity and visual appeal of your code. It enables you to call one method directly on another method that is part of the same object. In JavaScript, the keyword "this" signifies the current object in which it is being executed. Consequently, when a method returns "this," it essentially yields an instance of the object from which the method was invoked. Given that this returned value is an object instance, it allows for the subsequent invocation of another method on this instance, thus enabling method chaining in JavaScript.

Syntax

Example

ob = <some object>
ob.method_1().method_2().(some more methods).method_n()

Example 1

Without employing the chaining technique:

Example

<!DOCTYPE html>
<html>
<head>
</head>
<body>
   <h3>Displaying in output console </h3>
   <p> Output: </p>
   <div id="Result"></div>
   <div id="opError" style="color : red"></div>
   <script>
      var matter = ''
      var error = ''
      var opDiv = document.querySelector('#Result')
      var opErrDiv = document.querySelector('#opError')

      // here comes the javascript code
      try {
         let x = 'Welcome to the tutorial'
         x = x.toUpperCase()
         x = x.replace(/ /g, '&')    //it will globally replace all spaces with &
         x = x.trim()
         matter += "Value of x: " + JSON.stringify(x) + '<br>'
      }
      catch (err) {
         error += err
      }
      finally {

         // display on output console
         opDiv.innerHTML = matter
         opErrDiv.innerHTML = error
      }
   </script>
</body>
</html>

Output

Example 2

With the implementation of Method Chaining:

Example

<!DOCTYPE html>
<html>
<head>
</head>
<body>
   <h3>Displaying the output in Console </h3>
   <p> Output: </p>
   <div id="Result">
   </div>
   <div id="opError" style="color : blue">
   </div>
   <script>
      var matter = ''
      var error = ''
      var opDiv = document.querySelector('#Result')
      var opErrDiv = document.querySelector('#opError')

      //here javascript code starts
      try {
         let a = 'Now we will learn JavaScript in detail'
         a = a.toUpperCase().replace(/ /g, '@').trim()
         matter += "Value of a: " + JSON.stringify(a) + '<br>'
      }
      catch (err) {
         error += err
      }
      finally {

         // display on output console
         opDiv.innerHTML = matter
         opErrDiv.innerHTML = error
      }
   </script>
</body>
</html>

Output

Example 3

In the case of Method Chaining, the invocation of the method is placed on a separate line:

Example

<!DOCTYPE html>
<html>
<head>
</head>
<body>
   <h3>Displaying the output in console </h3>
   <p> Result: </p>
   <div id="Result">
   </div>
   <div id="opError" style="color : green">
   </div>
   <script>
      var matter = ''
      var error = ''
      var opDiv = document.querySelector('#Result')
      var opErrDiv = document.querySelector('#opError')

      // actual javascript code
      try {
         let b = 'JavaScript is a vast programming language'
         b = b
         .toLowerCase()
         .replace(/ /g, '%')
         .trim()
         matter += "Value of b: " + JSON.stringify(b) + '<br>'
      }
      catch (err) {
         error += err
      }
      finally {

         // display on output console
         opDiv.innerHTML = matter
         opErrDiv.innerHTML = error
      }
   </script>
</body>
</html>

Output

Example 4

The identical concept can be utilized with an array when we aim to employ multiple array methods in a series. Take a look at the example below that illustrates method chaining with an array.

For array objects that do not undergo method chaining:

Example

<!DOCTYPE html>
<html>
<head>
</head>
<body>
   <h3>Displaying the result in Console </h3>
   <p> Result: </p>
   <div id="Result">
   </div>
   <div id="opError" style="color : grey">
   </div>
   <script>
      var matter = ''
      var error = ''
      var opDiv = document.querySelector('#Result')
      var opErrDiv = document.querySelector('#opError')

      // actual javascript code
      try {
         let array = [2, 7,5, 4, null, 0, 9, null, 3, '30', 200]
         array = array.filter(z => typeof z === 'number' && isFinite(z))
         array = array.sort((a, b) => a - b)
         matter += "The final array after filtering: " + JSON.stringify(array) + '<br>'
      }
      catch (err) {
         error += err
      }
      finally {

         // display on output console
         opDiv.innerHTML = matter
         opErrDiv.innerHTML = error
      }
   </script>
</body>
</html>

Output

Example 5

Using the Chaining method on array objects:

Example

<!DOCTYPE html>
<html>
<head>
</head>
<body>
   <h3>Showing output in console </h3>
   <p> Result </p>
   <div id="Result">
   </div>
   <div id="opError" style="color : red">
   </div>
   <script>
      var content = ''
      var error = ''
      var opDiv = document.querySelector('#Result')
      var opErrDiv = document.querySelector('#opError')

      //Here actual javascript code starts
      try {
         let array = [10, 20, 30, 40, null, null, 50, 70, '10', 2000]
         array = array
         .filter(x => typeof x === 'number' && isFinite(x))
         .sort((a, b) => a - b)
         content += "The final list if array is: " + JSON.stringify(array) + '<br>'
      }
      catch (err) {
         error += err
      }
      finally {

         // display on output console
         opDiv.innerHTML = content
         opErrDiv.innerHTML = error
      }
   </script>
</body>
</html>

Output

Example 6

In JavaScript, asynchronous functions leverage promises to perform their tasks. Promises exemplify method chaining in this scenario effectively. To work with promises, it is necessary to initially construct the promise, and then create appropriate handler functions. These handler functions play a crucial role in managing the value once the promise has been fulfilled. Below is an example:

Utilizing a promise:

Example

<!DOCTYPE html>
<html>
<head>
</head>
<body>
   <h3>Showing result in output console </h3>
   <p> Result: </p>
   <div id="Result">
   </div>
   <div id="opError" style="color : green">
   </div>
   <script>
      var des = ''
      var error = ''
      var opDiv = document.querySelector('#Result')
      var opErrDiv = document.querySelector('#opError')

      //Here comes the actual JavaScript code
      try {

         // Creating a new Promise object
         const p = new Promise((resolve, reject) => {

            // making delay
            setTimeout(function () {

               // Resolve the promise by returning a message
               resolve('Message after utilizing promise')
            }, 2000)
         })
         .then(
          function (data) {
             des += "Data is fetching after promise: " + JSON.stringify(data) + '<br>';
             opDiv.innerHTML = des
         })
         .catch(err => error += "Error Message: " + JSON.stringify(err) + '<br>')
      }
      catch (err) {
         error += err
      }
      finally {

         // displaying the output on console
         opErrDiv.innerHTML = error
      }
   </script>
</body>
</html>

Output

Developing custom objects for method chaining in JavaScript

In the earlier examples, we examined how method chaining can be employed in JavaScript applications. In this segment, we will delve into the implementation of this technique for our custom objects. We will design a class that incorporates several functions, allowing them to be accessed via method chaining.

The 'this' keyword plays a crucial role in method chaining, as it denotes the object that is currently being utilized.

Example

Utilizing promises:

Example

<!DOCTYPE html>
<html>
<head>
</head>
<body>
   <h3>Showing output in console </h3>
   <p> Result: </p>
   <div id="Result">
   </div>
   <div id="opError" style="color : blue">
   </div>
   <script>
      var descr = ''
      var error = ''
      var opDiv = document.querySelector('#Result')
      var opErrDiv = document.querySelector('#opError')

      //Here comes the actual JavaScript code
      try {
         const person = {
            name: 'Yshakan',
            age: 23,
            state: null,
            currentState() {
               descr += "The current state of Yshakan is: " + JSON.stringify(this.state) + '<br>'
            },
            nowWake() {
               this.state = 'Wokeup'
               this.currentState()
               return this
            },
            playTennis() {
               this.state = 'Playing Tennis'
               this.currentState()
               return this
            },
            sleep() {
               this.state = 'Now Sleeping.'
               this.currentState()
               return this
            },
            eatFood() {
               this.state = 'Eating food.'
               this.currentState()
               return this
            },
            walk() {
               this.state = 'Walking in the morning.'
               this.currentState()
               return this
            },
            doWork() {
               this.state = 'Doing her work'
               this.currentState()
               return this
            }
         }
         person
         .sleep()
         .walk()
         .eatFood()
         .nowWake()
         .doWork()
         .sleep()
      }
      catch (err) {
         error += err
      }
      finally {

         // display on output console
         opDiv.innerHTML = descr
         opErrDiv.innerHTML = error
      }
   </script>
</body>
</html>

Output

In this example, it is clear that the functions provide the current object by utilizing the 'this' keyword. If this keyword were to be excluded, it would inhibit the ability to perform method chaining. In the example presented, the 'Person' class features a member variable referred to as 'state.' This variable is altered each time a method defined within the class is called. Consequently, these methods are carried out in succession through method chaining.

Conclusion

Method chaining is a prominent characteristic of JavaScript that helps in minimizing code size while simultaneously improving its clarity. This approach enables the execution of several methods on a single object in a linear sequence, thus negating the necessity of repeatedly assigning the same object with assignment operators. Method chaining proves to be particularly advantageous when working with asynchronous functions that rely on promises. In situations where data is fetched from a network, which may not align perfectly with code execution, it is essential to manage waiting times. Typically, there are two circumstances to consider: one where we define the procedures to be executed after the input has been handled, and another where we specify the actions to take in case an error occurs.

Input Required

This code uses input(). Please provide values below: