Skip to content
back to top
Just the code, please

Shailesh Codes

JAVASCRIPT IRL

Examples of JavaScript's reduce function in real life

By Shailesh Vasandani — Last updated on January 10, 2021 — Reading time: 7 min

javascript irl javascript frontend coding
More from JAVASCRIPT IRL
1

Real-life examples of JavaScript's map function

Sometimes it's easier to learn from examples — so here are some examples.

2
3

Real-life examples of JavaScript's filter function

The third and final part of a series on JavaScript's array functions.

JavaScript array methods are super useful, and learning how to use them can really help improve the readability of your code. This is the second part of a series on JavaScript array functions, where I dive into examples from real, production codebases. Today's function is reduce, which (for me at least) was the most abstract one of the three. By virtue of its abstractness, however, it's also the most powerful. In fact, it's possible to do the jobs of the other two using just reduce alone! (Even though you shouldn't. Definitely, absolutely, do not do this.)

Much like the map function, reduce is called on an array, and takes in two parameters: a callback, and an initial value. However, the callback looks a little different than the one in map — instead of taking one parameter, it takes two: an accumulator, and the current element. This gets to the very heart of the reduce function: starting with the initial value, it iterates over every element in the array, returning the result of the callback function as the accumulator to the next iteration of the loop. If that sounds confusing, don't worry. That's what the examples are for!

A trivial example

Before we get into code, I want to really drill down into what reduce does. An analogy that I found really helpful goes as follows:

Imagine a line (i.e. array) of people. You want to find the sum of their ages; that is, you want to reduce your array of people into a single number — their combined age. To do that, you'd probably use a calculator app and go down the line one person at a time, adding to your total as you go. That's exactly what the reduce function does — the initial value is 0, the accumulator is the running total in your calculator, and the current element is the person you're currently in front of.

With that in mind, let's see a simple example using the same sort of analogy:

        
      const arrayOfPeople = [
        {
          name: 'John Doe',
          age: 21
        },
        {
          name: 'Mary Sue',
          age: 34
        },
        {
          name: 'Gary Stu',
          age: 43
        }
      ];
      const combinedAge = arrayOfPeople.reduce((acc, curr) => acc + curr.age, 0);

      console.log(combinedAge); // => 98

To visualize how this works, use the same line of people analogy. Imagine you have a calculator, and you need to count the combined ages of these three people. You'd start off with 0 in your calculator — that's the initial value. Then you'd go up to John Doe, ask them their age, and add that to the value in your calculator. 0 plus 21 gives 21, so that's the running total so far. Then you'd go up to Mary Sue and ask them for their age. They say 34, so you add that to your calculator; 21 plus 34 gives 55, so now that's your running total. Finally, you'd go up to Gary Stu, ask them their age, and add that in. 55 plus 43 gives 98 — and that's exactly what reduce returns.

Now that we have that under our belt, let's look at some real-life examples:

Converting HTML nodes to strings

In this example, I was writing a feature for my blog that allowed the user to share a post to dev.to. I needed to select a bunch of tag elements on my page and convert them into a comma-separated string as part of the post frontmatter. This is the perfect use case for reduce; it takes an array of objects and squashes or reduces them down into a single value. Here's how I did it:

        
      const tagString = ` tags:${Array.from(document.querySelectorAll(".tags span.tag")).reduce((acc, curr) => { 
        return acc + (acc == "" ? "" : ", ") + curr.textContent;
      }, "")}` ;

Don't be fooled by the complicated looking ternary operator — it's only there to make sure that the first element doesn't have a comma before it. Otherwise, all the reduce function is doing is adding commas between the text contents of all of the tags.

Before we move on, a good question is why I couldn't use a function like join to do this. The answer is that you can't join an array of HTML nodes — you need to get their textContent property to see what they contain. What I could've done instead is map each element of the array to their textContent and then join them, but one method is much better than two. Hence, the reduce function. On an unrelated note, if you'd like to see some examples of the map function being used, be sure to check out my article.

With that said, let's look at another example:

Formatting comments

I recently implemented a comment section on my blog, and as part of that I wanted users to be able to apply basic formatting to their comments. This included bold, italics, code, and linebreaks. Because I didn't want to use any external libraries or parsers, however, I had to convert raw Markdown data into safe HTML elements. To do this, I needed to separate the input data by line, escape any HTML, and then run a custom Markdown converter on each line.

That seems like a lot, but it's the perfect job for a workhorse like reduce. I can perform the HTML escaping in the callback, and extract any useful code like the Markdown parsing to an external function. Here's what I ended up with:

        
      return body.split('\n').reduce((acc, curr) => {
        let text = document.createTextNode(curr);
        let p = document.createElement('p');
        p.appendChild(text);
        if (curr.trim().length === 0) return acc;
        return acc + (acc === "" ? "" : '</p><p class="comment-body">') + safeMarkdownToHTML(p.innerHTML);
      }, "");

The first few lines are just a way to leverage the browser's built-in HTML escaping with the createTextNode function. After that, I use a ternary operator (again!) to make sure that the first element doesn't have any unwanted content appended before it. Finally, I return the results of the (recursive) Markdown parsing function. While it may seem like a lot at first, by breaking it down into pieces, we can see how the final product is constructed. In this case, reduce serves as one tool among many to achieve this goal. By the way, let me know down in the comments if you'd like to see a post on parsing Markdown — it's a great introduction to recursion and string manipulation.

Let's take a look at one final example:

Making JavaScript effects accessible

On several pages on my website — my home page, blog page, and design page, for example — I use a typewriter effect as a bit of eye-candy. While cool-looking (I'm quite proud of the effect, to be honest), it's important to recognize that not everybody sees the internet in the same way. This effect in particular is quite inaccessible to people who use screen readers, so I had to find a way to convert the array of disparate words into one long phrase that could be read out via the aria-label attribute.

To do this concatenation, I once again reached for reduce. Because of the nature of the function, I was able to make a logical, grammatically correct sentence that would make sense when read out. Here's what that reduce function looked like in context:

        
      let t = new Typewriter(
        el, 
        el.dataset.speed, 
        el.dataset.pause, 
        JSON.parse(el.dataset.text), 
        [...new Set(JSON.parse(el.dataset.text))]
          .reduce((acc,curr) => acc + ", and " + curr.trim()), "")
      );

Super simple, super sweet — all I had to do was add ", and" between each element of the array. Again, I didn't end up using join because I had to call trim on each piece of text. Using reduce allows the array to be transformed and mutated while it's being collected, which is perfect for this use case. By the way, if you're interested in learning more about accessibility on the web, and in particular with JavaScript, be sure to subscribe to my mailing list — I'm going to have a lot of posts dedicated to the topic in the near to medium future.

Wrapping it up

I hope these examples gave you an idea of how the reduce function is really used in a codebase, and how it can help make code more readable and versatile. Let me know down in the comments if you have any interesting uses for the reduce function, and keep an eye out for the final post in the series!

As always, don't forget to follow me for more content like this. I'm currently writing on dev.to and Medium, and your support on either platform would be very much appreciated. I also have a membership set up, where you can get early previews of articles and exclusive access to a whole bunch of resources. Also, if you've particularly enjoyed this post, consider supporting me by buying me a coffee. Until next time!

Subscribe to my mailing list!

Hey there! Subscribe to my mailing list to get monthly updates on my most useful posts, and any special announcements I have. No spam, ever — promise. All fields are required.
Recommended for you

Low risk, high reward

An intro to site reliability engineering

CPR for your app: some tricks to try

What to do when your app just isn't running.

How to store data with IndexedDB

It's well supported, allows you to store large files, and isn't even that bad to work with.

Real-life examples of JavaScript's filter function

The third and final part of a series on JavaScript's array functions.

Comments

Write a comment!

All comments are moderated, and will only be published if they're constructive and add to the discussion. Thanks in advance! All fields are required.

copy