Functional Programming in Javascript for Busy People

Written by austin | Published 2020/01/17
Tech Story Tags: functional-programming | javascript | array | map | reduce | filter | js | web-monetization

TLDR 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.via the TL;DR App

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;
}, {});

Written by austin | Do not attempt to adjust your set. We are controlling transmission.
Published by HackerNoon on 2020/01/17