Introduction to higher order functions in Javascript

By definition, an higher order function is a function which, at least, receives one or more other functions as arguments or returns another function as its result. In this tutorial we will focus on standard library functions as filter, map and reduce: we will see when they can be useful and how to use them.

In this tutorial you will learn:

  • What is an higher order function.
  • Why we can use higher order functions in Javascript.
  • How and when to use filter, map and reduce functions.

javascript-logo

Software Requirements and Linux Command Line Conventions
Category Requirements, Conventions or Software Version Used
System Operating system agnostic.
Software An installation of node to follow this tutorial in a non-browser environment.
Other Knowledge of Javascript and object oriented concepts.
Conventions # – requires given linux commands to be executed with root privileges either directly as a root user or by use of sudo command
$ – requires given linux commands to be executed as a regular non-privileged user

What is an higher order function ?

In Javascript functions are first class objects: they can be assigned to variables, passed as arguments to other functions, or be returned by other functions. The use of higher order functions is based on this peculiarities. We define an higher order function as a function which at least accepts other functions as its arguments, or returns another function as its result. In this tutorial we will focus on standard library functions as filter, map and reduce.



In this tutorial, we will make a use of arrow functions: if you want to know more about this new function syntax, you could check this tutorial we published on the subject.

Filter or array.prototype.filter

The first function we will talk about is filter, or, to use its complete name, array.prototype.filter. This function is actually a method of the array object, and what it does it’s very simple: it returns a new array composed by the elements of the original array which pass the test implemented in its body.

To be clear, let’s see an example. Suppose we have an array of words and we want to “filter” words composed by exactly three letters. We could obtain what we want by using a for loop, writing:

const words = ["house", "pen", "book", "computer", "car"];
const shortWords = [];

// We could use a standard c-style for loop...
for (let i = 0; i < words.length; i++) {
  if (words[i].length == 3) {
    shortWords.push(words[i])
  }
}

//... or a for...of loop
for (let word of words) {
  if (word.length == 3) {
    shortWords.push(word);
  }
}

Both the examples above work, and the with both we achieve the same result. After the code is executed, the “shortWords” array will have two members: “pen” and “car”. You may notice, however, that especially the first example is pretty verbose. Let’s see how we can accomplish the same result with less code, by using filter:

const shortWords = words.filter((element) => element.length == 3);

We obtained the exact same result. There is, however, one difference: this time, by also using an arrow function, we wrote all in just one line of code!. Here is how filter works: it accepts only one “mandatory” argument which is another function, a callback.

This callback, accepts, in turn, one argument which is the element of the original array being currently processed. If the element passes the test (in this case if the length of the string is equal to 3), the element is inserted in the new array.

Map or array.prototype.map

The map (array.prototype.map) method, does something different. It also accepts a callback function as its only mandatory argument, but returns a new array composed by the elements resulting from applying said callback to all the elements of the original array.



An example will clarify everything. This time, suppose we want to obtain an array which should contain all the strings inside the “words” array, but in upper-case form. In just one line, we could write:

const uppercasedWords = words.map((element) => element.toUpperCase());

After executing the code above, the “uppercasedWords” array will be:

[ 'HOUSE', 'PEN', 'BOOK', 'COMPUTER', 'CAR' ]

The callback accepted as argument by map, has only one mandatory argument, which is the element of the original array which is being processed. The value resulting from applying the callback to each element of the original array is returned (remember: arrow functions without curly braces uses implicit return) and so added to the new array. The result, in this case, is a new array composed by the upper-case version of all the elements in the original one.

Reduce or array.prototype.reduce

The reduce, or array.prototype.reduce method works in a different way: it accepts a callback which takes two mandatory arguments. The first one is the so called accumulator, and the second one is the currentValue. Instead of producing a new array, this higher order function uses the provided callback, also called reducer, to reduce the array to one single value, which is returned. It is actually simpler than it looks, let’s see a basic example.

Suppose we have an array containing some numbers:

const numbers = [ 15, 0.50, 200 ];

Now, imagine we want to get the sum of all the numbers contained into the array. Again, we could use a loop, or, as we want to demonstrate, reduce, in the following way:

let totalPrice = numbers.reduce((accumulator, currentValue) => accumulator + currentValue);


The reduce method, as said above, accepts a callback function which takes two mandatory arguments. The first one is the accumulator: this argument will accumulate the results produced each time the callback function is called. The second one is currentValue, which represents the current element of the original array that is being processed.

One important thing to notice, is that, if no specified otherwise (we will see in a moment how we can do it), the first time the callback function is called, the value of the accumulator will be the first element of the array. We can realize that by simply logging the value of the accumulator and of the currentValue, each time the callback is executed:

let totalPrice = numbers.reduce((accumulator, currentValue) => {
  console.log(accumulator, currentValue);
  return accumulator + currentValue;
});

The output of the code above will be:

15 0.5
15.5 200

As you can notice, if an initial value for the accumulator is not explicitly provided, the first element of the array is used (15), and, very important thing, the index of the first element processed by the array, is1, so, in this case the first element to be processed is 0.5 (the second one).

If you think about it, this makes sense: otherwise the first element of the array would be counted two times! (It may be worth noticing that we could have specified manually the index of the first element of the array to be processed, by using the currentIndex optional argument of the callback, providing it after currentValue). As expected, the final value of totalPrice will be 215.5:

totalPrice
215.5

In the example above, the elements of the original array, “numbers”, were simple numbers, so primary types in Javascript. What if they were objects? Suppose we have an array of objects, each having three properties: a name, a price, and a price currency:

const items = [
  { name: 'book', price: 15, currency: 'EUR' },
  { name: 'car', price: 15000, currency: 'EUR' },
  { name: 'laptop', price: 1200, currency: 'EUR'}
];

What we want to obtain here, is the sum of all item prices. A problem immediately arises: we don’t want to sum each item of the array directly, since in this case we are working with objects, but the price property of each one. We should therefore make use of an optional parameter accepted by reduce, which is initialValue:

let finalPrice = items.reduce((accumulator, currentValue) => accumulator + currentValue.price, 0)

The finalPrice we obtain, as expected, is 16215. If we had not specified the initialValue, providing it after the callback function (0), the first element of the “items” array would have been used as the starting value for the accumulator. Since this is an object, the result would not have been as expected!

Conclusions

In this tutorial we learned to know what defines an higher order function, and why is it possible to use them in Javascript. We also learned to know and use three higher order functions contained in the standard Javascript library, such as filter, map and reduce. If you are interested in other Javascript topics, you can check our tutorials on promises or arrow functions.