Understanding ES6 – Higher-Order Functions

Introduction

In this article, we will first understand what a higher-order function is and then look at a few code examples of the popular higher-order functions such as forEach, map, filter, reduce, etc.

What are Higher Order Functions?

It is important to first understand what first-class citizens are before we move to higher-order functions.

First-Class Citizens

In JavaScript, functions are treated as ‘First Class’ citizens. The reason is that in JavaScript a function is fundamentally an object.

Let us take a quick example to explain this better. The below code is an example of a simple function.


function sayHello() {
    console.log('Hello');
}


sayHello(); 

When we say that Functions are objects, we can assign properties to the function similar to an object as shown below.


sayHello.greet = 'Namaste';

console.log(sayHello.greet); 

Note: While we can assign an attribute to a function. It is generally considered a bad practice. If you must add an attribute, then ensure you use an object.

You can also assign variables to a function as the code example shown below:


const sayHello = function() {
    console.log('Hello');
}


sayHello(); 

The above examples are that of ‘First-Class’ functions.

Higher-Order Functions

Higher-order functions are functions that take other functions as arguments or functions that return a function as their result.

The below code example will hopefully make the above explanation more clear.


const sum = function(a, b) {
    return a + b;
}


const higherOrderFunction = function(func, a, b) {
    return func(a, b);
}


console.log(higherOrderFunction(sum, 2, 3)); 

Things to note:

  • The function ‘higherOrderFunction’ accepts a function ‘func’ as a parameter.
  • The function ‘func’ that is passed in as a parameter is referred to as a callback.

Array.prototype.forEach, Array.prototype.map, Array.prototype.filter are few examples of high-order functions introduced with ES5.

Let’s dive into the actual functions.

Array.forEach

The forEach function was introduced with ES5 as Array.prototype.forEach and with ES6, it’s simply referenced as Array.forEach.

Syntax: Array.forEach( callback( currentValue, currentIndex, array));

The callback function receives three parameters:

  • The current element value – Mandatory
  • The current element index – Optional
  • The array that is being traversed.

Let us look at a code example:


const marvelMovies = [
  {
    title: "Iron Man",
    year: 2008,
  },
  {
    title: "The Avengers",
    year: 2012,
  },
  {
    title: "Doctor Strange",
    year: 2016,
  },
  {
    title: "Avengers: Infinity War",
    year: 2018,
  },
  {
    title: "Avengers: End Game",
    year: 2019,
  },
];



marvelMovies.forEach((movie) => {
  console.log(`The title of the movie is $${movie.title}`);
  console.log(`${movie.year} is the year the movie was released.`);
});


Things to note:

  • The callback function is an anonymous function. It is used in conjunction with an arrow function. If you would like a refresher on arrow function, you can read over here.
  • I have used ‘movie’ to reference the current element that is passed in as the argument. In reality, you can use any name to the variable you are referencing the current element.
  • The forEach loops through the ‘marvelMovies’ array and displays the title and the year of release on the console.

Array.map

The map function was introduced with ES5 as Array.prototype.map and with ES6, it’s simply referenced as Array.map.

Syntax: Array.map( callback( currentValue, currentIndex, array));

The callback function receives three parameters:

  • The current element value – Mandatory
  • The current element index – Optional
  • The array that is being traversed.

The important thing to note here is that the ‘map’ function returns a ‘new’ array with the results of the callback function applied to every element of the original array, in the same order.

Let us take the same marvelMovies array and use the map function to rate only the movies with the title ‘Avengers’.


const marvelMovies = [
  {
    title: "Iron Man",
    year: 2008,
  },
  {
    title: "The Avengers",
    year: 2012,
  },
  {
    title: "Doctor Strange",
    year: 2016,
  },
  {
    title: "Avengers: Infinity War",
    year: 2018,
  },
  {
    title: "Avengers: End Game",
    year: 2019,
  },
];



const newMarvelMovies = marvelMovies.map((marvelMovie) => {

        
    if(marvelMovie.title.includes('Avengers')) {
                
        marvelMovie['rating'] = 5;
    }
        
        
    return marvelMovie;
});


console.log(newMarvelMovies);


Things to Note:

  • The ‘map’ function returns a ‘new’ array.
  • In this example, I’ve used ‘marvelMovie’ name for the current element, just to demonstrate that any name can be used for referencing the current element.
  • The main use-case for a ‘map’ function is to edit or manipulate the elements of the array.

Array.filter

The filter function was introduced with ES5 as Array.prototype.filter and with ES6, it’s simply referenced as an Array.filter.

Syntax: Array.filter( callback( currentValue, currentIndex, array));

The callback function receives three parameters:

  • The current element value – Mandatory
  • The current element index – Optional
  • The array that is being traversed.

The filter function creates a new array with all the elements that pass the condition check specified in the callback function.

Let us look at the following code example:


const marvelMovies = [
  {
    title: "Iron Man",
    year: 2008,
  },
  {
    title: "The Avengers",
    year: 2012,
  },
  {
    title: "Doctor Strange",
    year: 2016,
  },
  {
    title: "Avengers: Infinity War",
    year: 2018,
  },
  {
    title: "Avengers: End Game",
    year: 2019,
  },
];




const filteredMarvelMovies = marvelMovies.filter((marvelMovie) => {
    return !marvelMovie.title.includes('Avengers');
});


console.log(filteredMarvelMovies);


Things to Note:

  • The ‘filter’ function returns a ‘new’ array.
  • The main use-case for a ‘filter’ function is to extract a specific sub-set of elements of the array matching a specific condition.

Array.some

The ‘some’ function was introduced with ES5 as Array.prototype.filter and with ES6, it’s simply referenced as Array.some.

Syntax: Array.some( callback( currentValue, currentIndex, array));

The callback function receives three parameters:

  • The current element value – Mandatory
  • The current element index – Optional
  • The array that is being traversed.

The ‘some’ function tests for whether at least one element in the array passes the test condition specified in the callback function. It returns a boolean value.

Let us look at the following code example:


const marvelMovies = [
  {
    title: "Iron Man",
    year: 2008,
  },
  {
    title: "The Avengers",
    year: 2012,
  },
  {
    title: "Doctor Strange",
    year: 2016,
  },
  {
    title: "Avengers: Infinity War",
    year: 2018,
  },
  {
    title: "Avengers: End Game",
    year: 2019,
  },
];




const checkTitle = marvelMovies.some(movie => {
    return movie.title === 'Thor'; 
});


console.log(checkTitle); 

I believe that the above code with the comments above is self-explanatory. Basically, the ‘some’ function checks if any one of the values in the array matches the condition (title matching ‘Thor’) and returns the value ‘false’, since there’s no matching value in the marvelMovies array.

Array.every

The ‘every’ function was introduced with ES5 as Array.prototype.every and with ES6, it’s simply referenced as Array.every.

Syntax: Array.every( callback( currentValue, currentIndex, array));

The callback function receives three parameters:

  • The current element value – Mandatory
  • The current element index – Optional
  • The array that is being traversed.

The ‘every’ function tests whether all the elements in the array pass the condition specified in the callback function. It returns a boolean value.

Let us look at the code example below:


const marvelMovies = [
  {
    title: "Iron Man",
    year: 2008,
    rating: 5
  },
  {
    title: "The Avengers",
    year: 2012,
    rating: 5
  },
  {
    title: "Doctor Strange",
    year: 2016,
    rating: 4
  },
  {
    title: "Avengers: Infinity War",
    year: 2018,
    rating: 5
  },
  {
    title: "Avengers: End Game",
    year: 2019,
    rating: 5
  },
];



const checkRating = marvelMovies.every(movie => {
    return movie.rating > 3; 
});


console.log(checkRating); 

Array.find & Array.findIndex

The find & findIndex were introduced with ES5 as Array.prototype.find & Array.prototype.findIndex. With ES6, they can be used as Array.find & Array.findIndex.

The Array.find function returns the first matching element based on the condition specified in the callback function.

The Array.findIndex function returns the index of the first matching element based on the condition specified in the callback function.

The code example below gives a quick example of how to use find & findIndex functions.


const marvelMovies = [
  {
    title: "Iron Man",
    year: 2008,
    rating: 4
  },
  {
    title: "The Avengers",
    year: 2012,
    rating: 3
  },
  {
    title: "Doctor Strange",
    year: 2016,
    rating: 4
  },
  {
    title: "Avengers: Infinity War",
    year: 2018,
    rating: 5
  },
  {
    title: "Avengers: End Game",
    year: 2019,
    rating: 5
  },
];



const found = marvelMovies.find(movie => {
    return movie.rating === 4; 
});


console.log(found); 





--------------------------------------------------------------------------



const foundIndex = marvelMovies.findIndex(movie => {
    return movie.rating === 4; 
});


console.log(foundIndex); 

Array.reduce

The ‘reduce’ function was introduced with ES5 as Array.prototype.reduce. With ES6, it’s simplified as Array.reduce.

Syntax: Array.every( callback( accumulator, currentValue, currentIndex, array));

The callback function receives four parameters:

  • The accumulator – Mandatory
  • The current element value – Mandatory
  • The current element index – Optional
  • The array that is being traversed.

The reducer function executes the callback function specified over each element of the array to finally return a single value.

In simplified words, through each iteration, the value returned by the callback function is assigned to the ‘accumulator’ and ultimately becomes the final single resulting value.

The reduce function is the one that’s most often not well understood. Hence, I’ll take an example without reducer and then use a reducer to explain the code flow.


const marvelMovies = [
    {
      title: "Iron Man",
      profit: 100000
    },
    {
      title: "The Avengers",
      profit: 200000
    },
    {
      title: "Doctor Strange",
      profit: 200000
    },
];    


let totalProfit = 0;



marvelMovies.forEach(movie => {
    totalProfit += movie.profit;
});


console.log(totalProfit);

Let us see how the above code can be simplified using the reduce function.


const marvelMovies = [
    {
      title: "Iron Man",
      profit: 100000
    },
    {
      title: "The Avengers",
      profit: 200000
    },
    {
      title: "Doctor Strange",
      profit: 200000
    },
];



const totalProfit = marvelMovies.reduce((accumulator, movie) => {
    return accumulator + movie.profit;
}, 0);


console.log(totalProfit);

Things to note:

  • The ‘reduce’ function takes in an ‘accumulator’ variable which holds the return value after every iteration.
  • In the example, the movie’s profit is added to the ‘accumulator’ exactly as how ‘total’ did in the previous example.
  • The main use case of a reduce function is whenever any computation in an array needs to result in a singular value.

Conclusion

To summarize, we started with understanding what higher-order functions are and then saw a few code examples for functions such as forEach, map, filter, reduce, same & every.

The important thing to remember is that both the functions map & filter return ‘new’ arrays.

The ‘map’ function is primarily used to manipulate the values of elements of the array based on a condition, whereas, a filter function is used to generally filter out few elements from the array based on a condition. They are very heavily used in actual real-world applications especially with the React framework.

I hope you enjoyed this article. Don’t forget to connect with me on Twitter @skaytech.

You will also enjoy the following articles:

Author: admin

Leave a Reply

Your email address will not be published.