DEV Community

Cover image for All Higher Order Functions Under the Hood in JavaScript
Gabriel Pedroza
Gabriel Pedroza

Posted on

All Higher Order Functions Under the Hood in JavaScript

forEach - (executes a function once per array element)

const forEach = (cb, array) => {
  for (let i = 0; i < array.length; i++) {
    cb(array[i], i, array)
  }
}
Enter fullscreen mode Exit fullscreen mode
array.forEach(function(currentValue, index, arr), thisValue)
Enter fullscreen mode Exit fullscreen mode

Iterating through an array declaratively using a callback function to manipulate the array respectively. Second param is undefined by default and when a value is passed to the function, it gets the this value. This is usually never used though.


map - (returns a new array from calling a function for every array element)

const map = (cb, array) => {
  const newArray = []
  for (let i = 0; i < array.length; i++) {
    newArray.push(cb(array[i], i, array))
  }
  return newArray
}
Enter fullscreen mode Exit fullscreen mode
array.map(function(currentValue, index, arr), thisValue)
Enter fullscreen mode Exit fullscreen mode

The key difference between map and forEach is map returns a new array and forEach returns undefined


filter (returns a new array filled with elements that pass a test provided by a function)

const filter = (cb, array) => {
  const newArray = []
  for (let i = 0; i < array.length; i++) {
    const element = array[i]
    if (cb(element, i, array)) newArray.push(element)
  }
  return newArray
}
Enter fullscreen mode Exit fullscreen mode
array.filter(function(currentValue, index, arr), thisValue)
Enter fullscreen mode Exit fullscreen mode

some (returns true on the first element that meets requirements; else, it will return false)

const some = (cb, array) => {
  for (let i = 0; i < array.length; i++) {
    if (cb(element, index, array)) return true
  }
  return false
}
Enter fullscreen mode Exit fullscreen mode
array.some(function(currentValue, index, arr), thisValue)
Enter fullscreen mode Exit fullscreen mode

every (returns false on the first element that fails to meet requirements; else, it will return true)

const every = (cb, array) => {
  for (let i = 0; i < array.length; i++) {
    if (!cb(element, index, array)) return false
  }
  return true
}
Enter fullscreen mode Exit fullscreen mode
array.every(function(currentValue, index, arr), thisValue)
Enter fullscreen mode Exit fullscreen mode

reduce (method returns a single value: the function's accumulated result)

function reduce(array, cb, initialValue) {
  let i = 1
  let currentValue = array[0]

  if (arguments.length > 2) {
    currentValue = initialValue
    i = 0
  }
  for (; i < array.length; i++) { // i has already been created, hence the lonely semi colon
    currentValue = cb(currentValue, array[i], i, array)
  }
  return currentValue
}
Enter fullscreen mode Exit fullscreen mode
array.reduce(function(total, currentValue, currentIndex, arr), initialValue)
Enter fullscreen mode Exit fullscreen mode

Very weird-looking under the hood but all it really does is it reduces what was passed into one value. It can be a number, array, object, etc... If the second argument is not passed, it will begin at the first index of the array; else, it will start at whatever you passed it. For example:


let sum = [0, 1, 2, 3].reduce(function (previousValue, currentValue) {
  return previousValue + currentValue
}, 0)
// sum is 6

Enter fullscreen mode Exit fullscreen mode

It takes the initial value that was passed, 0, and adds the first index. In this case, you would not need to pass the initialValue since you are just adding numbers and it will save you one operation. Another example using an object would be:


const names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice']

let countedNames = names.reduce(function (allNames, name) {
  if (name in allNames) {
    allNames[name]++
  }
  else {
    allNames[name] = 1
  }
  return allNames
}, {})
// countedNames is:
// { 'Alice': 2, 'Bob': 1, 'Tiff': 1, 'Bruce': 1 }

Enter fullscreen mode Exit fullscreen mode

This example will iterate through the array and check if the name already exists as a key in the object (the initial value is an empty object where you will store the result). If it already has created the name, it will add one more to it. One last example to truly make sure this is understood is:


const numbers = [-5, 6, 2, 0,];

const doubledPositiveNumbers = numbers.reduce((previousValue, currentValue) => {
  if (currentValue > 0) {
    const doubled = currentValue * 2;
    previousValue.push(doubled);
  }
  return previousValue;
}, []);

console.log(doubledPositiveNumbers); // [12, 4]

Enter fullscreen mode Exit fullscreen mode


This combines filter and map higher-order functions into a single reduce method which is a lot more efficient than traversing through the array twice. There is another hof called reduceRight and it does the exact same thing but traverses from right to left instead.

There are a lot of examples that go into reduce in the mdn so I'd recommend you check it out if you want to see the more complex examples. I hope this was helpful because not only this took time but also makes me appreciate the built-in methods by JavaScript. Don't forget to bookmark this because I know I will😎

Top comments (0)