Higher Order Functions

Higher Order Functions

In programming, a higher order function either

  • takes one or more functions as an argument

    or

  • outputs a function

Functions in JavaScript are just values, so they can be easily passed into and returned by functions.

The Bare Bones

Higher Order Functions are typically methods.

Methods - Methods are functions that are part of a bigger object. They can only be used when attached to an array, string, object, etc...

EX: item.function() or Array.map()

Functions = Functions are written to perform specific tasks but can be called whenever, they do not need to be attached to anything.

EX: function() or setInterval()

The bare bones of a Higher Order Function is this:

item.function(function(){}) if it is a method

or

function(function(){}) if it is just a regular function

Notice that the argument that a Higher Order Function takes is always another function. If you wanted to you could save that function to a variable beforehand and then just pass in that variable. That would look like this:

var myFunc = function(){};

function(myFunc);  

Common Higher Order Functions

Methods

  • .map()
  • .filter()
  • .reduce()
  • .sort()
  • .forEach()
  • .find()
  • .findIndex()
  • .some()
  • .every()

Functions

  • setInterval()
  • setTimeout()
  • clearInterval()

In this write up we are only going to be looking at the Methods. If you want to learn more or review your knowledge regarding setInterval, setTimeout, or clearInterval, you can do so here:

Examples

Let's begin with one of the more popular Methods.

.map() - Runs a for loop on an array and returns a new array with the changes indicated.

var arr = [1,2,3,4];

arr.map(function(item){  
    return item + 1;
})

// => [2,3,4,5]

Let's compare this to a normal for loop

var arr = [1,2,3,4];

for ( var i = 0; i < arr.length; i++){  
   arr[i] += 1;
}

// => [2,3,4,5]

They do virtually the exact same thing. One important thing to take note of is that rather than writing arr[i] to access each item in the array, we use item. The word item is not a saved word. Best practice is to name item the singular version of whatever your array holds, for example:

var dogs = ['lab', 'poodle', 'shih-tzu'];

dogs.map(function(dog){  
    return dog + 's are quite fancy';
})

// => ['labs are quite fancy', 'poodles are quite fancy', 'shit-tzus are quite fancy']

So if you had an array called numbers then the item would be number or if you had an array called names then the item would be name.

.filter() - Runs a loop on an array and returns a new array with only the items that meet the given condition.

var numbers = [12,4,56,27];

numbers.filter(function(number){  
    return number >= 25;
})

// => [56, 27]

So basically whatever you return inside the callback function is the condition that it will check for each item in the array. In the example above it went through each number in the numbers array and checked if it was greater than 25. If it was greater then it pushed it into the new array, if it was not, it did not include it in the new array.

Let's look at an example of this in the old way of writing for loops

var numbers = [12,4,56,27];  
var newArr = [];

for (var i = 0; i < numbers.length; i++){  
    if (numbers[i] >= 25){
        newArr.push(numbers[i]);
    }
}

// newArr => [56,27]

Comparing the two we see how much simpler and more concise the .filter is compared to the old way. Hopefully this demonstrates how useful Higher Order Functions can be!

.reduce() - Returns the sum of an array of numbers

var numbers = [1,2,3,4,5];

numbers.reduce(function(a,b){  
    return a + b
})

// => 15

.sort() - Returns a new array sorted either alphabetically or of numbers (low to high) or (high to low)

var scores = [12,98,34,85];

scores.sort(function(a,b){  
    return a - b
})

// => [12,34,85,98]

or if you want to sort it from High to Low

var scores = [12,98,34,85];

scores.sort(function(a,b){  
    return b - a
})

// => [98,85,34,12]

or if you want to sort words alphabetically

var words = ['bat', 'pineapple', 'drugs', 'zebra', 'ghost'];

words.sort()

// => ['bat', 'drugs', 'ghost', 'pineapple', 'zebra']

Notice the last one didn't take a function as an argument, you don't need it if you are alphabetizing words, only if you are ordering numbers.

.forEach() - Runs a loop on an array but does not create a new array. (basically the same as .map() but no new array is created)

var numbers = [1,2,3,4]

numbers.forEach(function(number){  
    return number * 2
})

// => [1,2,3,4]

Notice that no changes occurred. If we wanted to do the above code and have actual changes occur then we would have to do the following.

var numbers = [1,2,3,4]

numbers.forEach(function(number, i){  
    return numbers[i] = number * 2
})

// => [2,4,6,8]

There are some important things that happened here that we need to address.

  • We added i as the second parameter. Anytime a second parameter is given to .map, .filter, or .forEach, it becomes the index of that array.
  • Take note of the s at the end of numbers in the return statement. We are grabbing the index of the original array and we are not using the number parameter that we created in the callback function.
    • numbers[i] = number * 2 correct
    • number[i] = number * 2 incorrect

So what is the point of having forEach() if it doesn't save anything? Well it could be used for testing purposes if you wanted to see what happened without actually making any changes. Or it could be used to to run a function on each item. However, 9 times out of ten you will use .map over .forEach.

.find() - Returns the value of the first item in the array that meets the given condition.

var numbers = [12,30,5,62,18,53]

numbers.find(function(number){  
    return number > 50
})

// => 62

Remember this only returns the FIRST item that meets the given condition

.findIndex() - Returns the index of the first item in the array that meets the given condition.(exact same as .find() but it gets the index instead of the actual item)

var numbers = [12,30,5,62,18,53]

numbers.find(function(number){  
    return number > 50
})

// => 3

.some() - Checks if ANY items in an array meet a given condition and return True or False.

var numbers = [12,30,5,62,18,53]

numbers.find(function(number){  
    return number > 50
})

// => true

or

var numbers = [1,5,19,49,23]

numbers.find(function(number){  
    return number > 50
})

// => false

.every() - Checks if ALL items in a n array meet a given condition and returns True or False.

var numbers = [12,30,5,62,18,53]

numbers.find(function(number){  
    return number > 50
})

// => false

or

var numbers = [1,5,19,49,23]

numbers.find(function(number){  
    return number > 50
})

// => true

These are not all of the available Higher Order Functions, but these are the most common. I encourage you to familiarize yourself with these because they will be EXTREMELY useful throughout your coding career.