Three functional programming examples in JavaScript

door Chantal Steur - 20 oktober 2017

During my last assignment I had a colleague who suggested functional approaches on almost every pull request I made. Not being familiar with functional programming at all, it was difficult to wrap my head around what these changes exactly did. I dove into the world of functional programming, found out there was way too much to tell about, took a step back and decided to show some real life functional programming examples in JavaScript.

Use .map to transform arrays into anything

For what can’t you use .map! It is so useful and yet so simple! What .map does is call the same function for each element in an array with that element as a parameter and return all the outputted values in a new array. Below are some common examples:

Convert elements to a different type

const numbers = [1, 4, 6, 2];
const strings = numbers.map(n => `${n}`);

console.log(strings) // ['1', '4', '6', '2']

Get only the years from an array of dates

const dates = [1507239702976, 1201633297670, 1107388076393];
const years = dates.map(d => { return new Date(d).getFullYear() });

console.log(years) // [2017, 2008, 2005]

Get only the id’s from a list of products

const products = [{
    id: 232323,
    name: 'Shoe',
    price: 12.00
  }, {
    id: 242424,
    name: 'Glove',
    price: 15.00
  }];
const productIds = products.map(p => p.id);

console.log(productIds); // [232323, 242424]

Use .filter and .reduce

For mobile purposes I had to trim the months in a string to 3 characters with a dot:

On 2 november we tried to contact you would become: On 2 nov. we tried to contact you on mobile.

To do this I created the function getMobileMessage(). It does what it should do, but it sure takes some reading to understand what it exactly does. The second example however, is the same function using .filter and .reduce

The initial getMobileMessage()

See the Pen QqmJvB by Chantal Steur (@csteur) on CodePen.

getMobileMessage() using .filter and .reduce

See the Pen yzKwYx by Chantal Steur (@csteur) on CodePen.

That is quite some code line reduction! We managed to do the same with 2 lines of code. What exactly happens?

First it creates a new array, using .filter, of months that occur in the given string. The function that is passed as a parameter to .filter checks for each element if it occurs in the given string. Then with .reduce we create a new string that has the trimmed months.

A closer look at .reduce

Let’s step through the .reduce function to get a clear understanding of what it does. We will use the following string: ‘Both september and november rhyme with december’. In this case, .filter has returned [‘september’, ‘november’, ‘december’].

[code language="javascript"]
['september', 'november', 'december'].reduce((acc, month) => {
return acc.replace(new RegExp(month, 'g'), `${month.substring(0, 3)}.`)
}, 'Both september and november rhyme with december');
[/code]

As you can see, .reduce takes two parameters; the callback function to execute on each element in the array and the initial value of the accumulator (acc). This initial value is optional and if it is not set it is the first item in the array. What is the accumulator? This is the value that gets mutated and returned in each run. It is passed as the first parameter in the callback function. The second parameter in the callback function is the current item in the array. In this example the function runs 3 times since the array has a length of 3.

In the first run, acc will have the initial value: ‘Both september and november rhyme with december’. The second parameter, month, will have the value ‘september’ since it’s the first item in the array. Inside the callback function we can mutate acc; in this case it replaces all occurrences of the given month with a trimmed value. So acc will become ‘Both sep. and november rhyme with december’.

[code language="javascript"]
// first run
['september', 'november', 'december']
  // acc = 'Both september and november rhyme with december' and month = 'september'
  .reduce((acc, month) => {
  // returns 'Both sep. and november rhyme with december'
  return acc.replace(new RegExp(month, 'g'), `${month.substring(0, 3)}.`)
}, 'Both september and november rhyme with december'); // the initial value
[/code]

Now in the second run, acc gets passed from the previous run so its value will be ‘Both sep. and november rhyme with december’. The value of month is now ‘november’ since it’s the second item in the array. Same as in the first run, it will mutate acc by replacing occurrences of the given month, resulting in ‘Both sep. and nov. rhyme with december’.

[code language="javascript"]
// second run
['september', 'november', 'december']
  // acc = 'Both sep. and november rhyme with december' and month = 'november'
  .reduce((acc, month) => {
  // returns 'Both sep. and nov. rhyme with december'
  return acc.replace(new RegExp(month, 'g'), `${month.substring(0, 3)}.`) 
}, 'Both september and november rhyme with december'); // the initial value
[/code]

In the third run the exact same thing will happen as before, now with acc being ‘Both sep. and nov. rhyme with december’ and month being ‘december’ it will result in the final value of ‘Both sep. and nov. rhyme with dec.’ (that no longer rhymes…) After this run .reduce has finished and it will return the current value of acc.

[code language="javascript"]
// last run
['september', 'november', 'december']
  // acc = 'Both sep. and nov. rhyme with december' and month = 'december'
  .reduce((acc, month) => {
  // returns 'Both sep. and nov. rhyme with dec.'
  return acc.replace(new RegExp(month, 'g'), `${month.substring(0, 3)}.`)
}, 'Both september and november rhyme with december'); // the initial value
[/code]

Understanding what .reduce does and what it is capable of can really increase coding skills. Once the syntax has settled in your brain, it is actually really easy to write and most of all easy to read. Now when I see .reduce I know I only have to check the initial value and see what mutation the callback does. It saves a lot of time and of course lines of code.

3 Use recursion

Recursion (calling a function from inside that function) can be useful in some cases. In diehard functional programming, this is actually the only way to iterate. Using recursion in JavaScript is not necessarily better. It does reduce the usage of local variables and again, once the syntax is clear, it can also improve code readability. I personally prefer recursion over for instance a while loop because it just reads easier and it prevents the function from doing other stuff than it should do. When there is a lot to iterate over though, using recursion in JavaScript can cause a stack overflow. In such cases a regular loop might be the better option.

As part of generating a voucher code in which a digit was not allowed to occur more than twice, I needed a function that checked if the next given digit was valid. Below two solutions, one using a while loop and one using recursion.

Checking for double digits using a while loop

See the Pen EwRvQy by Chantal Steur (@csteur) on CodePen.

Checking for double digits using recursion

See the Pen YrvVwO by Chantal Steur (@csteur) on CodePen.

So that concludes three, straight from the branch, real life functional programming examples in JavaScript! Hope they can be of any use.