paint-brush
Functional Programming in Javascript for Busy Peopleby@austin
140 reads

Functional Programming in Javascript for Busy People

by Austin PocusJanuary 17th, 2020
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

You've probably used map, reduce, and other functional methods in Javascript before, but there are a few use cases you probably haven’t thought about much or used before. In this post, I’d like to go over these methods (and a few other surprises!) to show what’s possible in Javascript. The Hacker Noon codebase makes heavy use of map, filter, and reduce. In a simple example, we get the word count from both 2.0 and archived (1.0) stories, then sum the resulting array using reduce.

Company Mentioned

Mention Thumbnail
featured image - Functional Programming in Javascript for Busy People
Austin Pocus HackerNoon profile picture

You’ve probably used map, reduce, and other functional methods in Javascript before, but there are a few use cases you probably haven’t thought about much or used before. In this post, I’d like to go over these methods (and a few other surprises!) to show what’s possible.

Array#map

Map is the powerhouse of the cell, er, Javascript. It’s my favorite way to iterate over an array when I need a new value for each value in the array. In other words, if you need to transform an array element-by-element, map is the way to go. For example:

const squares = arr.map(i => Math.pow(i, 2));

You can also get the index as the second parameter of the callback, as in:

const nums = arr.map((i, idx) => {
  if (idx % 2 === 0) {
    return Math.pow(i, 2);
  } else {
    return Math.sqrt(i);
  }
});

This is a contrived example, but you get the picture. It gets more useful, though, when you factor in…

Array#reduce

Reduce is an efficient, expressive way to get a single value from a list of values. 

If you didn't know about reduce, you might do something like this:

let storyMap = {};
stories.map(story => {
  storyMap[story.slug] = story;
});

But with reduce, this can be made into:

const storyMap = stories.reduce((acc, story) => {
  acc[story.slug] = story;
  return acc;
}, {});

This, of course, is a contrived example, but you can clearly see how a more complex object might be built out of such a call. In this case,

acc
stands for "accumulator", the value that will eventually be passed out of reduce and into
storyMap
. If you pass a second parameter to reduce, as we have, that sets the initial value of the accumulator.

Let's look at a few real examples from the Hacker Noon codebase:

const words = stories.map(story => story.wordCount || story.words)
          .filter(wordCount => !!wordCount)
          .reduce((a, b) => { return a + b }, 0);

This example is fairly straightforward. We get the word count from both 2.0 and archived (1.0) stories, filter out any falsy/null values, then sum the resulting array using reduce.

As you can see, we make heavy use of map, filter, and reduce:

const storyMap = stories.reduce((acc, story) => {
  acc[`/${story.slug}`] = story;
  return acc;
}, {});

const storyMetrics = data.rows.reduce((acc, row) => {
  const pathname = row.dimensions[0];
  const story = storyMap[pathname];

  if (!story) { return acc; }

  const [pageviews, timeRead, avgTimeRead] = row.metrics[0].values;
  const metrics = { pageviews, time: timeRead };

  acc[story.id] = metrics;
  return acc;
}, {});