How JavaScript Higher Order Functions Work Under the Hood

Jaxongir - Sep 28 '22 - - Dev Community

Introduction

HOF stands for Higher Order Functions that is Array method and take callback as an argument and call it on each array iteration. Understanding how each Array methods work under the hood makes you a better Js developer. And in today' post I'm going to teach how Array methods work behind the scenes. Enjoy!

1. ForEach

ForEach method is used for side effects but the thing to note is that it does not mutate the original Array.
Steps

  1. call forEach on array
  2. pass callback to it
  3. followings happen within the forEach method body
    1. loop over the length of the current array
    2. on each iteration pass current item to the callback
    3. when loop ends, it returns undefined
  4. followings happen within the callback function body
    1. name the parameter passed by HOF
    2. do certain thing within the body
const names = ["Jaxongir", "Sarah", "Robert", "Joseph"];
Array.prototype.customForEach = function (callback) {
  for (const item of this) {
    callback(item);
  }
};
names.customForEach((name) => {
  console.log(`Hi ${name}`);
});
/**
Hi Jaxongir
Hi Sarah 
Hi Robert
Hi Joseph
 */

Enter fullscreen mode Exit fullscreen mode

2. Filter

Filter method is used to filter out not wanted items by setting conditional test and only keep the items that pass the test. And it does not mutate original array but returns the new filtered array
How it works

  1. call filter on the array
  2. pass callback to it
  3. followings happen within the filter method body
    1. create the empty array
    2. loop over the length of the current array
    3. call callback passed to it with the current item, and if returned value is truthy push current item to the new array else continue to the next iteration
    4. when the loop ends, return the new array
  4. followings happen within the callback function body
    1. name the parameter
    2. return either true or false based on which item you want to keep
const years = [2002, 1959, 2015, 2022, 1999];
Array.prototype.customFilter = function (callback) {
  const newArray = [];
  for (const item of this) {
    const isTrue = callback(item);
    if (isTrue) {
      newArray.push(item);
    }
  }
  return newArray;
};
const filteredYears = years.customFilter((year) => {
  return year >= 2000;
});
console.log(filteredYears);
// [2002, 2015, 2022]

Enter fullscreen mode Exit fullscreen mode

3. Map

Map method used to return new array that has the same length as the original array. Value of each item is decided by what's returned within the callback function's body
How it works

  1. call map on the array
  2. pass callback to it
  3. followings happen within the map method body
    1. create the empty array
    2. loop over the length of the current array
    3. call callback passed to it with the current item, and store the value returned by the callback on the array
    4. when the loop ends, return the new array
  4. followings happen within the callback function body
    1. name the parameter
    2. do some operation with the value passed to it and return it
const numbers = [5, 3, 9, 50, 200];
Array.prototype.customMap = function (callback) {
  const newArray = [];
  for (const item of this) {
    const newItem = callback(item);
    newArray.push(newItem);
  }
  return newArray;
};
const numbersMultipliedByTwo = numbers.customMap((number) => {
  return number * 2;
});
console.log(numbersMultipliedByTwo);
// [10, 6, 18, 100, 400]
Enter fullscreen mode Exit fullscreen mode

4. Some

Some method used to return true if only one of the items of the array satisfy conditional test in the callback function body.
How it works

  1. call some on the array
  2. pass callback to it
  3. followings happen within the some method body
    1. loop over the length of the current array
    2. call callback passed to it with the current item, and if returned value is truthy return true
    3. when the loop ends if none of the values pass the conditional test, return false to the next iteration
  4. followings happen within the callback function body
    1. name the parameter
    2. set up the conditional and return the result
const grades = [50, 40, 90, 20];
Array.prototype.customSome = function (callback) {
  for (const item of this) {
    const isTrue = callback(item);
    if (isTrue) {
      return true;
    }
  }
  return false;
};
const isEligible = grades.customSome((grade) => {
  return grade >= 75;
});
console.log(isEligible);
// true
Enter fullscreen mode Exit fullscreen mode

5. Every

Every method used to check if each array item passes the conditional test set up on the callback function body.
How it works

  1. call every on the array
  2. pass callback to it
  3. followings happen within the every method body
    1. loop over the length of the current array
    2. call callback passed to it with the current item, and if returned value is falsy then return false
    3. when the loop ends if each single item passed the test then return true
  4. followings happen within the callback function body
    1. name the parameter
    2. set up conditional and return the result
const grades = [50, 40, 90, 20];
Array.prototype.customEvery = function (callback) {
  for (const item of this) {
    const isFalse = callback(item);
    if (!isFalse) {
      return false;
    }
  }
  return true;
};
const isEligible = grades.customEvery((grade) => {
  return grade >= 40;
});
console.log(isEligible);
// true
Enter fullscreen mode Exit fullscreen mode

6. Find

Find method used to find single item from within the array.
How it works

  1. call find on the array
  2. pass callback to it
  3. followings happen within the find method body
    1. loop over the length of the current array
    2. pass current item the callback, and if returned value by callback is true then return current item else move to the next iteration
  4. followings happen within the callback function body
    1. name the parameter
    2. set up conditional test and return the result
const people = [
  { id: "1", name: "Jaxongir", country: "Uzbekistan" },
  { id: "2", name: "Sarah", country: "Poland" },
  { id: "3", name: "Arthur", country: "England" },
  { id: "4", name: "Jonathan", country: "USA" },
];
Array.prototype.customFind = function (callback) {
  for (const item of this) {
    const isFound = callback(item);
    if (isFound) {
      return item;
    }
  }
};
const person = people.customFind((person) => {
  return person.id === "1";
});
console.log(person);
// { id: "1", name: "Jaxongir", country: "Uzbekistan" },
Enter fullscreen mode Exit fullscreen mode

7. FindIndex

FindIndex method used to find the index of the first occurence of item that passes the conditional test set up by callback function.
How it works

  1. call findIndex on the array
  2. pass callback to it
  3. followings happen within the findIndex method body
    1. loop over the length of the current array
    2. pass current item to the callback, and if returned value by callback is true then return current item index
    3. when the loop ends, if item is not found the return -1
  4. followings happen within the callback function body
    1. name the parameter
    2. set up conditional and return the result
const people = [
  { id: "1", name: "Jaxongir", country: "Uzbekistan" },
  { id: "2", name: "Sarah", country: "Poland" },
  { id: "3", name: "Arthur", country: "England" },
  { id: "4", name: "Jonathan", country: "USA" },
];
Array.prototype.customFindIndex = function (callback) {
  for (let i = 0; i < this.length; i++) {
    const isFound = callback(this[i]);
    if (isFound) {
      return i;
    }
  }
};
const personIndex = people.customFindIndex((person) => {
  return person.id === "3";
});
console.log(personIndex);
// 2
Enter fullscreen mode Exit fullscreen mode

8. Push

Push method used to add new item to the end of the array and return the new array length. It mutates the original array
How it works

  1. call push on the array
  2. pass value or array of values that you want to add to the array
  3. followings happen within the push method body
    1. use rest operator to contain all values passed to push in the array
    2. loop over each item and push that item to the end of the current array
    3. when the loop ends, return the new length of the array
const hobbies = ["Cooking", "Reading"];
Array.prototype.customPush = function (...values) {
  for (const item of values) {
    this[this.length] = item;
  }
  return this.length;
};
console.log(hobbies);
// ["Cooking", "Reading"]
console.log(hobbies.customPush("Calisthenics", "Hiking", "Skiing"));
// 5
console.log(hobbies);
// [ 'Cooking', 'Reading', 'Calisthenics', 'Hiking', 'Skiing', 'Ring' ]
Enter fullscreen mode Exit fullscreen mode

9. Pop

Pop method used to remove item in the last index of the current array and return the removed item. And modifies the original array
How it works

  1. call pop on the array
  2. followings happen within the push method body
    1. store removed item in the variable
    2. remove the last item of the array
    3. return the removed array
const hobbies = ["Cooking", "Reading"];
Array.prototype.customPop = function () {
  const removedItem = this[this.length - 1];
  this.splice(this.length - 1, 1);
  return removedItem;
};
console.log(hobbies);
// ["Cooking", "Reading"]
console.log(hobbies.customPop());
// Reading
console.log(hobbies.customPop());
// Cooking
console.log(hobbies.customPop());
// undefined
console.log(hobbies);
// [ ]
Enter fullscreen mode Exit fullscreen mode
  1. Unshift Unshift method used to add new item to the beginning of the array and return the new array length How it works
  2. call unshift on the array
  3. pass value or array of values that you want to add to the array
  4. followings happen within the unshift method body
    1. use rest operator to contain all values passed to unshift in the array
    2. loop over each item and push that item to the beginning of the current array
    3. when the loop ends, return the new length of the array
const hobbies = ["Cooking", "Reading"];
Array.prototype.customUnshift = function (...values) {
  for (const item of values) {
    this.splice(0, 0, item);
  }
  return this.length;
};
console.log(hobbies);
// ["Cooking", "Reading"]
console.log(hobbies.customUnshift("Juggling", "Running"));
// 4
console.log(hobbies);
// ["Cooking", "Reading", "Juggling", "Running"]
Enter fullscreen mode Exit fullscreen mode
  1. Shift Shift method used to remove the first item in the array and return the removed item How it works
  2. call shift on the array
  3. followings happen within the shift method body
    1. store removed item in the variable
    2. remove the first item of the array
    3. return the removed array
const hobbies = ["Cooking", "Reading"];
Array.prototype.customShift = function () {
  const removedItem = this[0];
  this.splice(0, 1);
  return removedItem;
};
console.log(hobbies);
// ["Cooking", "Reading"]
console.log(hobbies.customShift("Juggling", "Running"));
// Juggling
console.log(hobbies);
// ["Running"

Enter fullscreen mode Exit fullscreen mode

Summary
So in this post we've learned how Array methods work under the hood. now as the challenge I want you guys, implement custom Array methods for methods not mentioned in here and share the result with me. I'm sure that you guys'll do it.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .