JavaScript - Higher Order Functions

As I start writing about various JavaScript features, one feature that pops into mind the most which is regularly used in other examples as well are Callback or Higher-order Functions. So, it is useful for u to discuss them and learn how they operate and what they mean. By understanding this, it will make our lives easier when learning other features and functionalities of JavaScript.

Keeping this in mind, let's dive into JavaScript Higher-Order Functions.

What are they?

A function that either accepts another function (as a parameter), returns another function (as a return value), or does both is referred to as a higher-order function.

The following is an illustration of a function that takes in a function:

document.querySelector("#container").addEventListener(
  "click",
  function(event){
    console.log(`You clicked on ${event.target.dataset.name}!`);
  }
)

Two parameters are being passed to the addEventListener function: the first is a string, and the second is a function. The Event API will accept that function and call it on our behalf when the associated event happens on that element.

This is an illustration of a function that returns a function:

const addTwoThings = function(first){
  return function(second){
    // and here, we have both first and second variables!
      return first + second;
  }
}

const add7 = addTwoThings(6);
const sayHello = addTwoThings("Hello, ");

// those are both now references to functions,
//   and those functions are scoped to unique instances of
//   addTwoThings. Let's see how we can use 'em:
console.log(sayHello("John")); // "Hello, John"
console.log(add7(32)); // 38

// Let's just complicate the crap out of things:
console.log(sayHello( add7( add7(45) ) ) ); // "Hello, 57"

Therefore, we are able to pass functions both ways.

Why are they important?

What makes this important? Think about the ES6 array methods, such as filter, map, forEach, reduce, some, and every. Each of them accepts a function, and we are passing in a function with extremely similar signatures to each of them. The interface is rather standard, which makes it a little bit simpler to recall how they operate.

Writing a map function to replicate the functionality of map in our own implementation may be a typical assignment in online courses. So as not to reveal the solution, let's attempt creating our own version of filter and see whether it might be successful.

First, we need to understand exactly what .filter() is doing, step by step. It is looping over the array, and testing each element in that array with a given function. The function takes in up to three parameters, the element, its index, and the original array reference, and returns a truthy or falsy value. If that returned value is truthy, we persist that element. If it is not, we don't. And then we return a new array, containing just the elements that met our function.

The term "predicate function" is frequently used to describe a function that returns a true or false value, as in "the choice was taken predicated on the outcome of this thing."

We want our myFilter to work the same way, so we would be able to call it like this:

// filter out every other element:
[1,2,3,4,5,6,7,8,9].myFilter((_, index)=>index%2===0);
// [1,3,5,7,9]

As a result, we will begin by creating a new Array method:

Array.prototype.myFilter = function( aFilterFunction ){
  let stuffWeWant = [];
  for(let i=0; i<this.length; i++){
    if( aFilterFunction(this[i], i, this) ){
      stuffWeWant.push(this[i]);
    }
  }
  return stuffWeWant;
}

We are receiving a function in our myFilter. The myFilter function executes that function for us. Just as we would, it calls the function and passes the required arguments.

By proxy, we are executing the function that was supplied. We only need to be aware that it is being sent in as a parameter so that we have a reference, and that it will either accept our defined parameters or it will fail. We don't need to know its name or where it originated from.

As a result, it is "higher-order" since we are entrusting myFilter with the execution of a function that we have passed to it.

I sincerely hope that the majority of you find the approach covered here to be helpful. Thank you for reading, and please feel free to leave any comments or questions in the comments section below.

Post a Comment

0 Comments