The reduce function is the most complex of the standard JavaScript array functions. With reduce, you can compress (reduce) an array to one element.

For the reduce function to work properly, you’ll need 2 parameters — the reducer function and the initial value.

The reducer function, unlike the functions you will use in map and filter, takes two parameters. The first is the accumulator. The second is the current element of the array.

Let’s see how we can calculate the sum of all elements of an array using reduce.

const arr = [ -1, 2, 4, 0, -5, 7 ];
const sum = arr.reduce((prev, cur) => prev + cur, 0);

console.log(sum); // 7

To make it a little clearer for you, I will rewrite this example using the for loop.

const arr = [ -1, 2, 4, 0, -5, 7 ];
let prev = 0; // accumulator

for (let i = 0; i < arr.length; i++) {
  // arr[i] is the current element of the array, same as cur in the reduce example
  prev = prev + arr[i]; 
}

const sum = prev;

console.log(sum); // 7

— This is clearer, but it looks like there is at least one extra line.

— It’s good that you pay attention to the extra code. The assignment sum = prev makes the for loop example as similar as possible to the previous one with reduce.

— Can you elaborate on the “initial value” that we pass as the second parameter?

— When the reduce function starts, it only has the first element of the array, so you need to add an initial value to start the calculations. Most often, this is an empty string, null, or an empty object.

Let’s see what happens if you try to reduce on an array of objects and don’t add an initial value.

Here’s an example of how you could calculate the total salary for the year of all employees of the company.

const employees = [
  { name: 'John Richards', salary: 155000 },
  { name: 'Lenny Mingles', salary: 75000 },
  { name: 'Travis Markham', salary: 102000 },
  { name: 'Bertha Jackson', salary: 47000 },
  { name: 'Vasya Pupkin', salary: 322000 },
];

const salariesSum = employees
  .reduce((prev, cur) => prev + cur.salary);

console.log(salariesSum); // [object Object]7500010200047000322000

As a result, a weird strange string [object Object]7500010200047000322000 was displayed in the console, due to the fact that we do not added the initial value of the accumulator.

Let’s add one console.log to better understand what prev is on each iteration:

const salariesSum = employees
  .reduce((prev, cur) => {
    console.log(prev); // added for debugging
    return prev + cur.salary
  });

New lines will appear in the console.

{name: 'John Richards', salary: 155000}
[object object]75000
[object object]75000102000
[object object]7500010200047000
[object object]7500010200047000322000

Here’s what happened:

  1. We did not specify the initial value of the accumulator and therefore the first element was used as the accumulator the employees array.
  2. By default, when trying to add an object to a number, both were converted to a string.
  3. On the second iteration in prev string [object Object]75000 which will stick together with numbers until it ends array.
  4. Eventually we will end up with the string [object Object]7500010200047000322000.

— It doesn’t look like the sum of salaries of all employees.

— You are right. Does not look like it. Fortunately, fixing the problem is very easy.

Let’s add the initial value of the accumulator and make sure that the salary is calculated correctly.

const employees = [
  { name: 'John Richards', salary: 155000 },
  { name: 'Lenny Mingles', salary: 75000 },
  { name: 'Travis Markham', salary: 102000 },
  { name: 'Bertha Jackson', salary: 47000 },
  { name: 'Vasya Pupkin', salary: 322000 },
];

const salariesSum = employees
  .reduce((prev, cur) => prev + cur.salary, 0);

console.log(salariesSum); // 701000

The reduce function can be combined with map and filter, but it is important that reduce is the last one in the chain.

Let’s try to calculate the total salary of those employees who earn more than one hundred thousand.

const employees = [
  { name: 'John Richards', salary: 155000 },
  { name: 'Lenny Mingles', salary: 75000 },
  { name: 'Travis Markham', salary: 102000 },
  { name: 'Bertha Jackson', salary: 47000 },
  { name: 'Vasya Pupkin', salary: 322000 },
];

const salariesSum = employees
  .filter(employee => employee.salary > 100000)
  .reduce((prev, cur) => prev + cur.salary, 0);

console.log(salariesSum); // 579000

Enough theory, it’s time to move on to practice!