This post will cover all the array helper functions available in ES6. Let's dive deep into each one of them.

Array.prototype.forEach()

forEach is one of the most commonly used ES6 helper functions. It's used to perform an action on each element present in the array. Thus, it essentially eliminate for-loops. It works by providing a callback which takes array element as the first argument and its index in the array as the second argument.

const arr = ['a', 'b', 'c'];

arr.forEach((letter, index) => {
  console.log(letter, index); // a 0, b 1, c 2
});

Array.prototype.map()

map is similar to forEach in that it iterates over each element in an array. But on top of that it creates a new array where the value of each element is the return value of a callback function on every element in the calling array.

const arr = [1, 2, 3];
const newArr = arr.map(num => num*2); // [2, 4, 6]

Array.prototype.filter()

filter returns a new array only with values where a callback function called on every element in the calling array returns true.

const arr = [1,2,3,4,5];
const newArr = arr.filter(num => num % 2 === 0); // [2, 4]

Array.prototype.find()

Whilst I have seen filter, forEach and map used all over the map, find array helper is less commonly used. It returns the value of the first element in the array that satisfies the condition in the provided callback function. undefined is returned if no element satisfies the requirements.

const arr = [1,2,3,4,5];
const evenNumber = arr.find(num => num % 2 === 0); // 2

Array.prototype.some()

some is another somewhat esoteric array helper which returns a boolean value based on whether at least one element in the array satisfies the condition in the callback function.

const arr = [1,2,3,4,5];
const atLeastOneEven = arr.some(num => num % 2 === 0); // true

Array.prototype.every()

every is very similar to some except that here we test whether all elements satisfy a give condition. In the given example not all numbers are even and thus the result ends up as false.

const arr = [1,2,3,4,5];
const allEven = arr.every(num => num % 2 === 0); // false

Array.prototype.reduce()

reduce is the most confusing, at least for me, and yet the most flexible array helper function. It takes a callback function where the first argument is an accumulator to which the results will be applied to, and then the current element in the array.

const arr = [1,2,3,4,5];
const total = arr.reduce((total, value) => total + value); // 15

The above example sums up all elements in the array and assigns the result to total. However, reduce is much more powerful than that. For example, it can be used in creating a tally.

We can do so by assigning an initial value of {} passing it as second argument to reduce, and then inside the reducer tallying up all the fruits. Not sure if tallying is even a word though 😂

const arr = ['banana', 'orange', 'apple', 'orange', 'banana', 'orange'];
const tally = arr.reduce((tally, fruit) => {
  tally[fruit] = (tally[fruit] || 0) + 1;
  return tally;
}, {}); // { banana: 2, orange: 3, apple: 1 }

Performance

Out of interest I also attempted to do a small benchmark study to get an idea of how ES6 array helpers performance differs from the traditional for-loop.

The below graph is for forEach and it speaks for itself. forEach performance time seems to grow almost expotentially whilst for-loop is fairly linear. The same scenario occured for all other helpers.

See the Pen forEach vs. for-loop by Karolis (@karolis) on CodePen.

Based on the benchmark results I would not recommend forEach or any other ES6 helper discussed in this article for large arrays and would only use them for extra readability where array size is relatively small and performance is not super critical.

Below you can see the sample code used for the benchmarks.

const TRIES_PER_TEST = 20;
const TEST_SIZES = [100, 1000, 10000, 100000, 250000, 500000, 1000000, 2500000, 5000000, 10000000, 25000000, 50000000];

const generateArray = n => {
  const arr = [];
  for (let i = 0; i < n; i++) {
    arr.push(Math.random());
  }

  return arr;
};

const performTest = (fn) => {
  let timeBefore, timeAfter, total = 0;

  for (let i = 0; i < TRIES_PER_TEST; i++) {
    timeBefore = performance.now();
    fn();
    timeAfter = performance.now();
    total += timeAfter - timeBefore;
  }

  return total / TRIES_PER_TEST;
}

for (let testSize of TEST_SIZES) {
  let arr = generateArray(testSize);

  let forEachTime = performTest(() => {
    arr.forEach(number => number);
  });

  let forLoopTime = performTest(() => {
    for (let i = 0, n = arr.length; i < n; i += 1) {
      arr[i];
    }
  });

  console.log(`${testSize}: forEach => ${forEachTime} ms, for-loop => ${forLoopTime} ms`);
}