An Introduction To Javascript Higher Order Functions

Ian Lenny
7 min readMar 16, 2020

In this article we are going to explore some of the finer points of Javascript’s built in Array methods .map and .every. In doing so we will explore the broader topics of imperative vs. declarative programming, abstractions and higher order functions. My hope is that by the end of this article, you will have a new appreciation for the immense power of Javascript’s higher order functions.

Abstractions

In the context of programming, abstractions “hide the details and let us talk about problems from a higher (or more abstract) level”. -Eloquent Javascript

This is important since abstracting away complexity is one of the main things programmers do to simplify the problem solving process. This happens in all phases of the problem solving process from understanding the problem and writing pseudocode to refactoring a working solution.

One of the hallmarks of a good programmer is the ability to identify complexity that can be abstracted away into a modular piece of code that can be called on when needed or ignored when not in use.

Functions are the basic “modular” units of code that encapsulate a single process. One of the simplest ways to make your code easier to understand is to have each of your functions perform just one process.

Higher Order Functions

Higher order functions are functions that are passed other functions as arguments or return functions. Higher order functions allow us to build complex processes using the using individual functions as “building blocks”. These higher order functions allow us to create new processes while avoiding the issues associated with overly complex individual functions. This allows us to create any functionality we need using a simple 2 step process:

  1. Abstract away a program’s complex functionality into individual processes (functions)
  2. Assemble complex, multi-step processes by passing functions as arguments to other functions.

For a more in depth discussion of this process refer to the use of function composition in mathematics and computer science.

Declarative vs. Imperative Programming

Comparing and contrasting these two styles of programming is integral to a deep understanding of Javascript’s higher order functions. Beyond our specific use case, having this understanding will make you a more versatile developer.

Imperative programming focuses on step-by-step instructions for the execution of a process. Imperative style programming reads like a recipe (do this, then do that, then do this, etc…).

Declarative style programming states what happens without describing many of the details of how a process takes place.

As a programmer abstracts away individual processes into functions and uses function composition, their code becomes more declarative. In the next section we will explore this process of moving from imperative to declarative forms of code through the use of Javascript’s Array.prototype.map and Array.prototype.every methods.

Array.prototype.map

The .map function is an Array method that returns a new array. An inner callback function is passed to .map as an argument. This function is executed once for each value in the array .map is called on. This callback function returns the result of this transformation to the .map function which adds each transformed value to array it returns to the caller.

let new_array = arr.map(callback( currentValue[, index[, array]]) {
// return element for new_array
}[, thisArg])

The above example shows the standard syntax for Array.prototype.map. Array arr calls .map which takes 2 arguments, callback and thisArg. The parameter callback is mandatory, meaning the .map method requires an argument to be passed to it.

The callback function callback has 3 parameters. One mandatory parameter currentValue and 2 optional parameters index and array. currentValue represents the current value of the calling array that is being passed to the callback function. index (optional) is the index of the calling array that contains the current value being passed to the callback function. array (optional) is the array that the .map method is being called on.

The second (optional) parameter used by the .map method is thisArg. This parameter allows you to manually define the object that this refers to during execution of the callback. This optional argument allows you to assign an object to this so that you can work with the assigned object’s properties during the execution of the callback.

A simple example of the type of problem the .map method is used to solve is shown below. In this example we will start with the imperative style of code:

let numbers = [1, 2, 3, 4, 5];
let tripledNumbers = [];

for (let index = 0; index < numbers.length; index += 1) {
let currentNum = numbers[index];
let tripledNum = currentNum * 3;

tripledNumbers.push(tripledNum);
}

tripledNumbers; // => [ 3, 6, 9, 12, 15]

In the above example, we initialize array numbers containing primitive values 1 through 5. We then initialize an empty array tripledNumbers. Next we create a for loop that loops through every index of the array numbers by starting at index 0 and incrementing by 1 until it reaches the index at numbers.length — 1.

For each value of index a new value currentNum is initialized and set to equal the value of the numbers array at the index equal to index. A second variable tripledNum is then initialized with a value of three times the value of currentNum.

Finally the value of tripledNum is pushed into the array tripledNumbers. After the for loops completes its last iteration, tripledNumbers contains an array of the values from array numbers tripled.

Contrast this imperative style of coding with the more declarative implementation using the .map method (shown below).

let numbers = [1, 2, 3, 4, 5]; 
let tripledNumbers = numbers.map(currentNum => currentNum * 3); tripledNumbers; // => [ 3, 6, 9, 12, 15 ];

In the above example .map is called on array numbers. A callback function is passed to map as an argument. .map calls the callback function once for each element in numbers, passing each value as an argument to the callback one-at-a-time. After the callback transforms an element of numbers it returns the transformed vales to the caller, .map. Once the last value is returned, the .map method returns a new array containing the values returned to it after each execution of the callback.

Array.prototype.every

The second array method we will look at is .every. This method answers the question “does every element in the array pass some condition”. This method returns a boolean value indicating whether or not the condition, defined by the callback, has been satisfied for each element in the calling array.

arr.every(callback(element[, index[, array]])[, thisArg])

The above example shows the standard syntax for Array.prototype.every. Array arr calls .every which takes 2 arguments, callback and thisArg. The parameter callback is mandatory, meaning the .every method requires an argument to be passed to it.

The callback function callback has 3 parameters. One mandatory parameter element and 2 optional parameters index and array. element represents the current element of the calling array that is being passed to the callback function. index (optional) is the index of the calling array that contains the current element being passed to the callback function. array (optional) is the array that the .every method is being called on.

The second (optional) parameter used by the .every method is thisArg. This parameter allows you to manually define the object that this refers to during execution of the callback. This optional argument allows you to assign an object to this so that you can work with the assigned object’s properties during the execution of the callback.

A simple example of the type of problem the .every method is used to solve is shown below. This is a program that checks to make sure that each element of an array is below a certain threshold. In this example we will start with the imperative style of coding:

let arr = [4, 5, 6];
let condition = true;
for (idx = 0; idx < arr.length; idx += 1) {
if (arr[idx] <= 5) {
condition = false;
}
}
return condition; // false

In the above code we initialize array arr. We then initialize a variable condition with the boolean value true to keep track of whether or not the condition is being met for all elements of array arr. We then enter a for loop that will loop through each element of array arr by starting at index 0 and incrementing by 1 until the index arr.length — 1 is reached, causing the for loop to terminate.

For each iteration of the loop we are checking to see if the element of array arr at index idx is less then or equal to 5 if (arr[idx] <= 5). If the element at this index is less than 5, condition is set to equal false. If just one of the elements in the array arr is less then or equal to five the program returns false.

As with the 1st example of an imperative style of code, this program is verbose. Compare this program with a declarative approach that uses the .every method (shown below):

let arr = [4, 5, 6];
arr.every(num => num > 5); //false

In this example, .every is called on array arr. Each element of arr is passed to the inner callback function one-at-a-time. The inner callback is a function that takes just one argument num and returns the result of the conditional statement num > 5 to the caller, in this case the .every method. If the callback returns false for any element in array arr, .every will return false.

Further Exploration

At this point it should be clear that Javascript’s built in array methods abstract away large amounts of complexity. The two brief examples above highlight how much is going on “under the hood” when the .every and .map methods are called.

Using array methods saves time and creates programs that are less verbose. Comparing the two styles of coding back to back highlights the advantage of using Javascript higher order functions.

To really gain an appreciation of all that is going on in the background of these method’s execution, it is necessary to look at a “built from scratch” implementation of .map and .every. If you’re interested in checking these out, you can start with the polyfill section of the Mozilla Developer Network documentation for each method (reference 4 and 5).

Refrences

[1] https://eloquentjavascript.net/05_higher_order.html

[2] https://dev.to/damcosset/higher-order-functions-in-javascript-4j8b

[3] https://www.freecodecamp.org/forum/t/how-to-use-javascript-array-prototype-map-javascript-map-explained-with-examples/14294

[4] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map#Polyfill

[5] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every

[6] https://www.w3schools.com/jsref/jsref_every.asp

[7] https://blog.bitsrc.io/functional-programming-in-javascript-how-and-why-94e7a97343b

[8] https://www.bitdegree.org/learn/javascript-foreach

--

--