DEV Community

Excel Bill
Excel Bill

Posted on

Understanding the Compose Function in JavaScript

One of my least favourite concepts in JavaScript had to be the compose and pipe functions, I mean, they are great functions and definitely save a lot of time, but while learning it, it just looked like a bunch of functions returning each other, it was difficult to understand what was really happening.

In this article, we'll be going over the compose function line by line while I explain like to a toddler.

Before we start, you atleast need a little knowledge of javaScript.

What is a compose function

The compose function is a higher-order function that takes two or more functions as arguments and returns a new function that applies these functions in a right-to-left order. Basically, a compose function receives a bunch of functions as argument and then sends them to another function inside of itself which applies them from right to left using the reduceRight method in javaScript. et's dive right into it.

Given a typical compose function;

function compose(...funcs) {
  return function(arg) {
    return funcs.reduceRight((accum, fn) => {
      return fn(accum);
    }, arg);
  };
}
Enter fullscreen mode Exit fullscreen mode

Let's break it down line by line and digest it

function compose(...funcs) {
Enter fullscreen mode Exit fullscreen mode

This is the beginning of a function called compose(the function doesn't have to be called compose). It takes any number of arguments (functions) and stores them in an array using the spread operator(...).

return function(arg) {
Enter fullscreen mode Exit fullscreen mode

Here we return a function which recieves a single argument, the argument it recieves is going to be the element which these functions will be exercuted on.

return funcs.reduceRight((accum, fn) => {
Enter fullscreen mode Exit fullscreen mode

This line starts a reduceRight method on the funcs array(remember the array was created virtually, using spread[...] operator), which applies the callback function to each element in the array, starting from the right side. If you don't understand, don't fret, I'll still explain how the reduce function works as you read down.

return fn(accum);
Enter fullscreen mode Exit fullscreen mode

This line applies each function in funcs to the accum variable. accum is initially set to the value of arg (the argument passed to the returned function), and it gets updated each time a function in funcs is applied to it.

}, arg);
  };
}
Enter fullscreen mode Exit fullscreen mode

Finally, we set the initial value of accum to the value of arg.

The reduceRight function

In JavaScript, the reduceRight method takes a callback function as its first argument, which is used to apply a given operation to each element in the array, and reduce the array to a single value. The callback function takes two arguments: the accumulator (which starts as the last element in the array) and the current value (which starts as the second-to-last element in the array).

In the compose function, the callback function being used with reduceRight is an arrow function with two parameters: accum and fn. accum is the accumulator that gets passed from one iteration to the next, and fn is the current value being processed by the reduceRight method.

The callback function returns the result of applying fn to accum. This means that each function in funcs is being applied to the previous result, and the final result is the output of the last function in the array after it has been applied to the previous result.

How the compose function executes

Let me walk you through an example callstack for the compose function to demonstrate how it works.

Let's say we have the following functions:

function addOne(x) {
  return x + 1;
}

function double(x) {
  return x * 2;
}

function square(x) {
  return x * x;
}
Enter fullscreen mode Exit fullscreen mode

And we call compose like this:

const composedFunction = compose(square, double, addOne);
const result = composedFunction(2);
console.log(result); // Output: 36
Enter fullscreen mode Exit fullscreen mode

Here's what happens step by step:

  • we call compose with the arguments square, double, and addOne
const composedFunction = compose(square, double, addOne);
Enter fullscreen mode Exit fullscreen mode
  • Inside the compose function, the reduceRight method is called on the funcs array ([square, double, addOne]). The initial value of the accumulator (accum) is set to the value of the argument passed to the returned function (arg), which in this case is 2.
result = 2;
Enter fullscreen mode Exit fullscreen mode
  • The first iteration of the reduceRight method starts, with fn set to addOne. The function is called with accum as the argument, and returns the value 3. This becomes the new value of accum.
accum = addOne(accum); // result = 3
Enter fullscreen mode Exit fullscreen mode
  • The second iteration of the reduceRight method starts, with fn set to double. The function is called with accum as the argument, and returns the value 6. This becomes the new value of accum.
accum = double(accum); // result = 6
Enter fullscreen mode Exit fullscreen mode
  • The third and final iteration of the reduceRight method starts, with fn set to square. The function is called with accum as the argument, and returns the value 36. This becomes the final value of acuum.
accum = square(accum); // result = 36
Enter fullscreen mode Exit fullscreen mode

The returned function from compose is called with the argument 2. This function applies each function in the funcs array to the argument in a right-to-left order. First, addOne is called with the argument 2, which returns 3. Then, double is called with the argument 3, which returns 6. Finally, square is called with the argument 6, which returns 36

So, in summary, the compose function takes any number of functions as arguments and returns a new function that applies these functions in a right-to-left order. The returned function takes a single argument and applies each function in the provided array to it, starting from the right side. By doing this, we can create a new function that is composed of multiple smaller functions, which can make our code more modular and easier to read.

As usual thank you for reading and I hope you got value for your time. Follow me @frontend_jedi to find more educating reads. Follow me on twitter @Frontend_Jedi let's connect and grow together.

Top comments (0)