Function Composition in JavaScript Explained with Examples

Functional programming: function composition is an excellent way to maintain clean, readable code when executing long procedures.

Joshua Tal
JavaScript in Plain English

--

In this article, we will briefly introduce the concept of function composition and talk about how it can make JavaScript projects more readable. Then, we’ll discuss a working example in order to demonstrate just that.

So what’s function composition anyway?

Mathematically, function composition is applying one function to the results of another, for example:

Given:
g(x) = x + 5
f(x) = x / 2
Let's evaluate: f(g(5))First...
g(5) = 5 + 5
//we get 10
Then...
f(10) = 10 / 2
//we get 5
So... f(g(5)) = 5

If you got that, great! But we are programmers, not mathematicians right? So how might we define that in comp sci terms?

“Function composition is the process of combining two or more functions to produce a new function. Composing functions together is like snapping together a series of pipes for our data to flow through.” — Eric Elliot, Master the JavaScript Interview: What is Function Composition?

Let’s try it out now in ES6:

Ok. That feels fine for now but what happens when we need to compose more and more functions? Say something like:

a(b(c(d(e(5))))

That’s not very pleasant to read anymore, is it? Here’s where the common use compose function comes to the rescue.

Compose

Compose will take the output from one function and automatically patch it to the input of the next function and repeat that process again and again until it spits out the final value. We can either use a library (like ramda or lodash) or make our own compose method as so:

Basically, this higher-order function accepts any number of functions as a parameter then returns a function that will invoke those given functions from right to left. You can read more about how it works here. It’s kind of confusing so let’s try it out using the example we introduced earlier:

It might not feel like a significant difference now but consider when compositions get really big, for example:

a(b(c(d(e(5))))becomes...compose(a,b,c,d,e)(5)

Talk about fewer parentheses and more readability, am I right?

A working example

Let’s explore the compose function as it’s used to instantiate a matching game for an educational app that teaches Hebrew verb conjugations. In the end, here’s what we should expect to see:

Assume we are given an array of conjugation_pronoun objects (in Spanish, for same ASCII-character purposes) as such:

Forgetting all the nitty-gritty styling details and just focusing on JavaScript for now, how can we turn that data into our final product? We should consider the following things: The matching game presents six cards in total. Three verb conjugations and three pronouns. Also, the cards are randomly ordered. Based on these considerations, the procedural steps to initializing our matching game must be:

1. Randomly select 3 conjugation_pronoun objects
2. Separate pronouns and conjugations
3. Shuffle the object (card) order
4. Display the UI

First, let’s build our helper methods.

Next, assuming that we have a function called displayUI which takes our final output and presents all the cards on the screen, let’s explore a few different ways we can tie our helper methods together.

That’s really messy, reminds me of chaining, and not likely to get you to be the most popular developer on the team. I think another problem here is the potential to get caught up in super deeply nested function calls which is something we want to avoid.

How about this?

That’s a bit nicer but I think there’s still a way to remove the unnecessary wordiness. We can also remove the need to declare one-time-used variables.

Let’s try using our compose function:

Look at that! It works great!

Conclusion

By leveraging the compose function we managed to execute all the necessary tasks and arrive at the same goal with a much more concise, readable, yet just as descriptive few lines of code.

Feel free to check out the source code to the full app here. I also recommend checking out the lodash or ramda libraries if you intend on using compose and/or functions like it.

Thanks!

--

--