Composing Functions in JavaScript
Tags: node, javascript, webdev
Published: 2020-03-18 04:12:46

Find me on [medium](https://medium.com/@jsmanifest)

What makes JavaScript my favorite language to be writing apps with is abilities to compose so many different kinds of functions together that can eventually lead to a working program.

We see JavaScript code everywhere that demonstrates this in different ways.

Composing functions together can become extremely fun especially when they work. Unfortunately it's not always an easy thing to pull off because writing composed code has to be done without any errors or else it simply won't run.

In JavaScript, there are rules to composing things like functions together.

In this article, we will go over some examples of composing in JavaScript and talk about important concepts that always need to be kept in mind when composing.

## What does it mean to compose?

_Composing_ means to combine more than one thing to build a _bigger_ thing. It's a general concept in mathematics where you combine two or more functions into a brand new function. Most of us have been working with this concept growing up in school, in the form of something like `f(g(x))` which is pronounced "f of g of x".

In JavaScript, it can look like this:

```js
const f = console.log
const g = (str) => `Hello, ${str}`
const sayWord = (x) => f(g(x))

sayWord('bryan') // "Hello, bryan"
```

Let's talk about composing functions. When we compose functions together, the main goal is to take a function and combine it with another function--so that when both of them are together gives us a more enhanced function that helps to produce a value that we want. There's multiple good reasons why people prefer to compose functions, such as reducing code and providing a more convenient reusable piece of code.

In JavaScript, functions are considered first-class meaning they can be passed around and can take on the disguise of a "value", just like strings, numbers, booleans, objects, etc. What it means is that it allows functions to _take other functions as arguments_ and can even _return functions_. This is what makes JavaScript a very powerful language because you can throw them around anywhere you want.

Let's look at an example of a function that appends `'hello'` to a string:

```js
function append(str) {
  return `hello ${str}
}
```

It's easy to use this function and receive a string back like so:

```js
const result = append('Gary') // 'hello Gary'
```

But as we just learned, functions can take functions so lets just use the second argument and test out what we can do just by adding a function argument to the function:

```js
function append(str, modify) {
  return `hello ${str}
}
```

Okay, we now left an opening for the second argument to do something inside here. Just by doing this simple change it opened up for some additional functionality, like this for example:

```js
function append(str, modify = (s) => s) {
  return `hello ${modify(str)}`
}

function capitalize(value) {
  return value.toUpperCase()
}

const result = append('boss', capitalize) // 'hello BOSS'
```

Because of how flexible JavaScript can be as we've seen above, learning how to compose functions in JavaScript is one of most important skills to pick up when developing JavaScript apps!

## Why is it important to compose?

As mentioned earlier, there are multiple good reasons to why people compose functions.

Let's look at this scenario:

```js
function doubleTheNums(obj) {
  const keys = Object.keys(obj)
  for (let index = 0; index < keys.length; index++) {
    const key = keys[index]
    const innerObj = obj[key]
    const innerObjKeys = Object.keys(innerObj)
    for (let innerIndex = 0; innerIndex < innerObjKeys.length; innerIndex++) {
      const innerObjKey = innerObjKeys[innerIndex]
      const innerObjKeyValue = innerObj[innerObjKey]
      if (typeof innerObjKeyValue === 'number') {
        innerObj[innerObjKey] = innerObj[innerObjKey] * 2
      }
    }
  }
  return obj
}

const results = {
  game1: {
    lakers: 40,
    celtics: 40,
    overtime: {
      lakers: 48,
      celtics: 58,
    },
  },
  game2: {
    lakers: 40,
    celtics: 21,
  },
  game3: {
    lakers: 12,
    celtics: 29,
  },
}

console.log(doubleTheNums(results))
```

result:

```json
{
  "game1": {
    "lakers": 80,
    "celtics": 80,
    "overtime": {
      "lakers": 48,
      "celtics": 58
    }
  },
  "game2": {
    "lakers": 80,
    "celtics": 42
  },
  "game3": {
    "lakers": 24,
    "celtics": 58
  }
}
```

The `doubleTheNums` function is responsible for looking at an object and doubling its number value if its a `number` type. Why should we turn this into a composed function instead? Lets look at some problems that the current function is having first:

1. If the object passed in was deepy nested the code will just keep awkwardly being pushed down right like a tree shape. But ain't no one got time for that kinda thing.
2. If the object passed in was deeply nested we unnecessarily lose valuable brain energy running out of ideas to name the inner variables (`innerObjKey`, `innerObjKeyValue` might lead to `deeplyInnerObjKey`, `deeplyInnerObjKeyValue`, `innerInnerInnerObjKey`, `innerInnerInnerObjKeyValue`, etc)
3. The code gets repetitive over time. This might confuse us and no one wants to be confused.
4. File size is increasing

Thank the heavens we can easily just throw functions around and call it a day:

```js
function doubleTheNums(obj) {
  const keys = Object.keys(obj)
  for (let index = 0; index < keys.length; index++) {
    const key = keys[index]
    const value = obj[key]
    if (typeof value === 'number') {
      obj[key] = obj[key] * 2
    } else if (value && typeof value === 'object') {
      doubleTheNums(obj[key])
    }
  }
  return obj
}

const results = {
  game1: {
    lakers: 40,
    celtics: 40,
    overtime: {
      lakers: 48,
      celtics: 58,
    },
  },
  game2: {
    lakers: 40,
    celtics: 21,
  },
  game3: {
    lakers: 12,
    celtics: 29,
  },
}

console.log(doubleTheNums(results))
```

result:

```json
{
  "game1": {
    "lakers": 80,
    "celtics": 80,
    "overtime": {
      "lakers": 96,
      "celtics": 116
    }
  },
  "game2": {
    "lakers": 80,
    "celtics": 42
  },
  "game3": {
    "lakers": 24,
    "celtics": 58
  }
}
```

The technique we just used was called _recursion_ which is a very useful technique that solves all the problems we layed out previously.

The point is, that the fact that we can use functions so freely in JavaScript makes composing functions a _very important topic_! However, if you're new to programming then it's worth noting here that composing functions to create more enhanced, complex ones is a common utility in any programming language. But we'll focus on JavaScript because obviously this post is about JavaScript.

If you've looked at source codes of JavaScript libraries then you've probably been exposed to a good amount of code examples that do really well in composing functions. You might have also realized that the majority of these composed functions are composed of much smaller, modular functions.

Lets take a look at a function that does nothing:

```js
function doNothing(obj) {
  return obj ? obj : obj
}

const result = doNothing({ name: 'Bob' })
```

We can create a `compose` function that takes a bunch of functions to create one more function where it can be used the same way:

```js
const compose = (...fns) => (arg) =>
  fns.reduceRight((acc, fn) => (fn ? fn(acc) : acc), arg)
```

Now we can take a bunch of useless functions at once while still keeping the same functionality!

```js
function doNothing(obj) {
  return obj ? obj : obj
}

function doSomethingButNothingStill(obj) {
  if (obj) {
    obj = obj
  }
  return obj ? obj : obj
}

const evaluateSomething = compose(
  doSomethingButNothingStill,
  doNothing,
)

const result = evaluateSomething({
  name: 'Bob',
  lastName: 'Lopez
})
```

In a real world scenario it's useful because you might need to take multiple functions that have the same signature to produce a final value. If multiple functions have the same signature and they're all going to get called through the same value for example then that's when it's a good time to use the composer:

```js
const compose = (...fns) => (arg) =>
  fns.reduceRight((acc, fn) => (fn ? fn(acc) : acc), arg)

const add = (num1) => (num2) => num1 + num2
const multiply = (num1) => (num2) => num1 * num2
const subtract = (num1) => (num2) => num1 - num2

const composedOperations = compose(add(5), multiply(2), subtract(3))

const compute = (arr, initialNum = 0) =>
  arr.reduce((acc, val) => composedOperations(acc), initialNum)

console.log(compute([-10, 25, 55, 22], 6))
```

In the last example, if we needed to use several math operations we decided to compose multiple math operator functions to produce the final value. This made it a little more convenient since ultimately we would still have ended up passing the same argument to the functions as we loop through the array of numbers.

### Injecting callbacks to be used in conjunction with existing ones

The possibilities of good uses for composing functions are endless. But to wrap this article up we'll go over another useful use case so that you can have a better understanding of how functions can be composed to achieve a variety of scenarios.

We'll be looking at a scenario for a react app next.

Imagine we're building a button component. It's going to have an `onClick` event listener so that when users click on it it will receive the event and alert the `name` of the `currentTarget` element that was clicked:

```jsx
import React from 'react'

function MyButton({ children, ...rest }) {
  return (
    <button onClick={(e) => window.alert(e.currentTarget.name)} {...rest}>
      {children}
    </button>
  )
}

function App() {
  return (
    <div>
      <MyButton name="alerter">Alert</MyButton>
    </div>
  )
}

export default App
```

What if later on we want to add an additional `onClick` handler to the same button from outside, for additional behavior? We can easily achieve this goal by doing this:

```jsx
import React from 'react'

function MyButton({ children, onClick: onClickProp, ...rest }) {
  return (
    <button
      onClick={(e) => {
        window.alert(e.currentTarget.name)
        if (onClickProp) {
          onClickProp(e)
        }
      }}
      {...rest}
    >
      {children}
    </button>
  )
}

function App() {
  function onClick(e) {
    console.log('Here is the event object', e)
  }
  return (
    <div>
      <MyButton name="alerter" onClick={onClick}>
        Alert
      </MyButton>
    </div>
  )
}

export default App
```

But that isn't a good solution because if we had other components that need this functionality we have to repeat this process. It also makes the handler really awkward afterwards.

A function that composes multiple `onClick` functions to create an _enhanced_ `onClick` function is probably a better idea because you can re-use it for other event handlers like `onMouseOver`, `onMouseLeave`, etc. Here's a function we can use to solve the last problem we had:

```jsx
function callAll(...fns) {
  return (...args) => fns.forEach((fn) => fn && fn(...args))
}
```

Now we can use it to replace our ugly solution with an elegent one:

```jsx
import React from 'react'
import callAll from '../utils/callAll'

function MyButton({ children, onClick: onClickProp, ...rest }) {
  function onClick(e) {
    window.alert(e.currentTarget.name)
  }
  return (
    <button onClick={callAll(onClick, onClickProp)} {...rest}>
      {children}
    </button>
  )
}

function App() {
  function onClick(e) {
    console.log('Here is the event object', e)
  }
  return (
    <div>
      <MyButton name="alerter" onClick={onClick}>
        Alert
      </MyButton>
    </div>
  )
}

export default App
```

It basically achieves the same thing. But it's important to keep in mind that when you compose functions, most of the time you should be _aware of the signature of the functions that you are composing_!

For example in our `callAll` we had to ensure that none of the functions we composed had a possibility of being given a completely different value as the first argument. In our earlier example with `compose`, this was the case because the result of each function was passed as the first argument to the next function in the pipeline. In `callAll`, a `.forEach` ensured that each function in the pipeline receives the event object each time because by definition it doesn't return anything to the caller even if it tried to return one.

Find me on [medium](https://medium.com/@jsmanifest)