Let's implement the reduce method by refactoring a for-loop
Tags: javascript
Published: 2020-06-03 02:38:50

The goal of this post is to show you how the reduce method works and can be implemented by slowly refactoring a simple for loop. Each step will modify one part of the code and at the end we will have an implementation of the reduce method.

_originally published on [uncomma.com](https://alex.uncomma.com/kinda-code/let-s-implement-the-reduce-method-by-refactoring-a-for-loop)_

### From a for-loop to reduce
Let's start with a simple script to sum an array of numbers. We define an array, a sum, then loop over each element, adding to the sum. At the end of the script, we print the sum to view the result.

```javascript
const arr = [1, 2, 3, 4, 5];
var sum = 0;

for (let n of arr) {
  sum += n;
}

console.log(sum);
// 15
```

We can make this more general and create a sum function that takes an array as an argument and returns the sum of the elements.

This function looks a lot like the script above. It sets the initial state to zero and loops over the array, adding each element to the state. After the loop, the state is returned. We can use this function on any array of numbers now.

```javascript
const sum = (arr) => {
  var state = 0;
  for (let n of arr) {
    state = state + n;
  }
  return state;
};

sum([1, 2, 3, 4, 5]);
// 15
```

Now we will start generalizing even more, working our way towards reduce. Rather than hard coding how the state is updated, lets move it into a function. In this next script, "state + n" is replaced with a function call.

```javascript
var addToSum = (s, val) => s + val;

const sum = (arr) => {
  var state = 0;
  for (let n of arr) {
    state = addToSum(state, n);
  }
  return state;
};

sum([1, 2, 3, 4, 5]);
// 15
```

And we keep generalizing. Let's replace addToSum with an argument function. Now our sum function takes a second argument: adderFn. Now, when we call sum, we pass in a function that adds the next number (n) to the state (s).

```javascript
const sum = (arr, adderFn) => {
  var state = 0;
  for (let n of arr) {
    state = adderFn(state, n);
  }
  return state;
};

sum([1, 2, 3, 4, 5], (s, n) => s + n);
// 15
```

We have one more hardcoded value that we can remove from the function: the initial state. Let's just pass state as an argument.

```javascript
const sum = (arr, adderFn, state) => {
  for (let n of arr) {
    state = adderFn(state, n);
  }
  return state;
};

sum([1, 2, 3, 4, 5], (sum, n) => sum + n, 0);
// 15
```

Now we have a function that takes an array, a function, and an initial state. It loops over the array, updating the state by passing the current state and current element to the argument function. This is reduce!

Let's update some variables names and remove any reference to our sum function.

```javascript
const reduce = (arr, reduceFn, state) => {
  for (let el of arr) {
    state = reduceFn(state, el);
  }
  return state;
};

reduce([1, 2, 3, 4, 5], (s, n) => s + n, 0);
```

We can define this function on the array prototype, so it looks like the native reduce. The main difference is we no longer take an array argument.

```javascript
Array.prototype.reduce = function(reduceFn, state) {
  for (let el of this) {
    state = reduceFn(state, el);
  }
  return state;
};

[1, 2, 3, 4, 5].reduce((s, n) => s + n, 0);
```


And that's it. We just refactored a simple for loop into the reduce function.

Check out some reduce examples here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce#Examples

If you like this style of post, sign up for the newsletter [here](https://alex.uncomma.com/kinda-code/let-s-implement-the-reduce-method-by-refactoring-a-for-loop) or know on twitter [@xwle](https://twitter.com/xwle)