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.
E.g.: 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()
- Returns a new array with a change made to every item from the original array
- Whatever you return from the inner function is inserted into the same index as the original array
- .filter()
- Returns a new array that only includes some of the items from the original array
- If inner function returns
true
(or something "truthy"), that item is included in the new array. If it returnsfalse
(or something "falsey"), it doesn't include it in the new array.
- .reduce()
- Returns any kind of value you want (number, string, boolean, array, etc.)
- Inner function used to combine the values from the original array into a single value of some kind. E.g.: adding all the values together from an array of numbers.
- .sort()
- Modifies/mutates the original array by re-ordering the items therein.
- Inner function compares 2 items and determines how they should be reordered.
- .forEach()
- Returns
undefined
(don't expect to receive anything in return) - Runs the inner function once for every item in the original array
- Returns
- .find()
- Returns one of the items from the array
- If inner function returns
true
, the.find()
finishes and returns that current value in the original array. If it returnsfalse
, it continues to search through the array until it returnstrue
. If it never returnstrue
(no items match the condition), it returnsundefined
- .findIndex()
- Same as
.find()
but instead of returning the item in the array, it returns the index where it found the matching item
- Same as
- .some()
- Returns either
true
orfalse
- If inner function returns
true
, the.some()
immediately returnstrue
(because at least one of the items matches your condition). If the inner function returnsfalse
for every item in the array, the.some()
returnsfalse
(no items matches your condition)
- Returns either
- .every()
- Returns
true
orfalse
- Opposite of
.some()
, in that if the inner function ever returnsfalse
for any item,.every()
immediately returnsfalse
(because NOT every item matched the condition). If the inner function returnstrue
for every item in the array, the.every()
returnstrue
- Returns
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() - Modifies original 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 ofnumbers
in the return statement. We are grabbing the index of the original array and we are not using thenumber
parameter that we created in the callback function. numbers[i] = number * 2
correctnumber[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.findIndex(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.some(function(number){
return number > 50
})
// => true
or
var numbers = [1,5,19,49,23]
numbers.some(function(number){
return number > 50
})
// => false
.every() - Checks if ALL items in an array meet a given condition and returns True or False.
var numbers = [12,30,5,62,18,53]
numbers.every(function(number){
return number > 50
})
// => false
or
var numbers = [1,5,19,49,23]
numbers.every(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.