Understanding array.reduce by creating its polyfill
Tags: javascript, programming, beginners, tutorial
Published: 2021-10-23 15:16:53

One of the most complex array method is `array.reduce`. So in this article we will learn about the **reduce** function while making its polyfill.(A [polyfill](https://developer.mozilla.org/en-US/docs/Glossary/Polyfill) is a piece of code used to provide modern functionality on older browsers that do not natively support it).

Okay let's start from the beginning. The `reduce` function takes a callback function. So the way we would use it is:
```js
let arr = [1, 2, 3, 4, 5]
arr.reduce(function(){
    console.log("hello")
})
```
Now if we run this you will see
![basic array reduce call](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0gt0tayom37ujdqrv80k.png)
hello was printed on console 4 time. But notice that our array has 5 elements. So the **reduce** function will be called `array.length - 1` times. So we can easily mimic this behaviour by using a simple for loop.
```js
function myReduce(arr, cb){
    for(let i = 0; i < arr.length - 1; i++){
        cb()
    }
}

let arr = [1, 2, 3, 4, 5]
myReduce(arr, function(){
    console.log("hello")
})
```
If you run this code you will see the output is the same. But this is not that useful. So lets move on.
When the `reduce` function calls the callback function it also passes some arguments to it. Lets `console.log` the first two arguments it receive.
```js
let arr = [1, 2, 3, 4, 5]
arr.reduce(function(a, b){
    console.log(a, b)
})
```
![printing value received from reduce](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1b8mmu2o1ijqdktk4r50.png)
The output looks really weird. At first the value of **a** was the first element in array and value of **b** was the second element of our array. After that in next function calls the value of **a** was `undefined` and the value of b was the next elements in our array. What's happening? Let's try to return something in our callback function.
```js
let arr = [1, 2, 3, 4, 5]
arr.reduce(function(a, b){
    console.log(a, b)
    return "hello"
})
```
![returning value in reduce cb](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kl0vvuaf6wig4mg6hyq4.png)
Okay it looks like initially the value of **a** is the first element of our array after that what ever we return from our callback function the value of **a** will become that. So lets do that in our custom function.
```js
function myReduce(arr, cb){
    let a = arr[0]
    for(let i = 0; i < arr.length - 1; i++){
        //setting the value of a to what ever the call back returns
        a = cb(a, arr[i])
    }
}

let arr = [1, 2, 3, 4, 5]
myReduce(arr, function(a, b){
    console.log(a, b)
    return "hello"
})
```
![returning value in myReduce cb](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/te0dfo75xwljpplapnbb.png)
Seems like our output is a little different. To fix that instead of saying `for(let i = 0; i < arr.length - 1; i++)` we can say `for(let i = 1; i < arr.length; i++)`
```js
function myReduce(arr, cb){
    let a = arr[0]
    for(let i = 1; i < arr.length; i++){
        //setting the value of a to what ever the call back returns
        a = cb(a, arr[i])
    }
}

let arr = [1, 2, 3, 4, 5]
myReduce([1, 2, 3, 4, 5], function(a, b){
    console.log(a, b)
    return "hello"
})
```
![returning value in myReduce cb](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y4j1hx6veccpbzh3sl4e.png)
And now our outputs are the same.

The `reduce` function can also take a second argument. So let's see what happens if we pass a second argument.
```js
let arr = [1, 2, 3, 4, 5]
arr.reduce(function(a, b){
    console.log(a, b)
    return "hello"
}, "Hi") //passing hi as second argument
```
![second value passed in array reduce](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jbmrnr9kh3fru8at1nec.png)
So it looks like if we pass a second value to out `reduce` function the initial value of **a** will be what we pass after that it will be what we return from the callback function. And the value of **b** will starts from the first element of our array. Well then, lets add this logic to our custom JS function as well.
```js
function myReduce(arr, cb, initialVal){
    let a = arr[0]
    let startIdx = 1

    if(initialVal){
        a = initialVal
        startIdx = 0
    }
    
    for(let i = startIdx; i < arr.length; i++){
        //setting the value of a to what ever the call back returns
        a = cb(a, arr[i])
    }
}

let arr = [1, 2, 3, 4, 5]
myReduce(arr, function(a, b){
    console.log(a, b)
    return "hello"
}, "Hi")
```
![custom array reduce demo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/st5olgtolhhmm5qmo2af.png)

Okay we are doing progress. Now our array reduce function also returns something. lets `console.log` it.
```js
let arr = [1, 2, 3, 4, 5]
let res = arr.reduce(function(a, b){
    console.log(a, b)
    return "hello"
}, 0)
console.log("res: " + res)
```
![array reduce demo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1rt11i1qrb6g0102etg7.png)
it looks like it also returns hello. Okay let's try to return something new from the callback function. We can return `a + b`. So each time the callback function is called the value of **b** will be added to **a**
```js
let arr = [1, 2, 3, 4, 5]
let res = arr.reduce(function(a, b){
    console.log(a, b)
    return a + b
}, 0)
console.log("res: " + res)
```
![array reduce demo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r4zc2plbkvzp1zhtowa6.png)
 
Here we can see after the last callback function call value of **a** was 10 and **b** was 5. so the callback function returned `10 + 5` which means the final value of **a** will be 
`10 + 5` or `15` and our reduce function is also returning `15`. So the reduce function will return the final value of **a**.
Now lets make our custom function do that as well
```js
function myReduce(arr, cb, initialVal){
    let a = arr[0]
    let startIdx = 1

    if(initialVal){
        a = initialVal
        startIdx = 0
    }
    
    for(let i = startIdx; i < arr.length; i++){
        //setting the value of a to what ever the call back returns
        a = cb(a, arr[i])
    }

    return a //returning the final value of a
}

let arr = [1, 2, 3, 4, 5]
let res = myReduce(arr, function(a, b){
    console.log(a, b)
    return a + b
}, 0)
console.log("res: " + res)
```
![custom array reduce demo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wvedt429cgb649b7r7xg.png)
Almost there. Now instead of having to say `let res = myReduce(arr, ...)` I should be able to say `arr.myReduce`. To do so we need to add `myReduce` to `array`s prototype.
```js
Array.prototype.myReduce = function(cb, initialVal){
    let arr = this //'this' is the array on which this function was called
    let a = arr[0]
    let startIdx = 1

    if(initialVal){
        a = initialVal
        startIdx = 0
    }
    
    for(let i = startIdx; i < arr.length; i++){
        //setting the value of a to what ever the call back returns
        a = cb(a, arr[i])
    }

    return a //returning the final value of a
}

let arr = [1, 2, 3, 4, 5]
let res = arr.myReduce(function(a, b){
    console.log(a, b)
    return a + b
}, 0)
console.log("res: " + res)
```
![final demo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sf6f2smavbktrmx6hipg.png)
And there you go. Now you not only know how the `reduce` function works, you have created your own reduce function from scratch. Now to polish your skills you can check [this link](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce) 
 and these examples
1. Getting the sum of array ```js
let arr = [1, 2, 3, 4, 5]
let sum = arr.reduce(function(a, b){
    return a + b
})
//or using arrow function
let sum = arr.reduce((a, b) => a + b)
console.log(sum) //output: 15
```
2. Remove duplicates from array
```js
let arr = [1, 2, 2, 3, 4, 4, 5]
let newArr = arr.reduce((a, b) => {
    if(a.indexOf(b) == -1) a.push(b)
    return a
}, [])

console.log(newArr) //output: [1, 2, 3, 4, 5]
```
3. Find the largest number in array
```js
let arr = [2, 5, 345, 32, 52]
let max = arr.reduce((a, b) => {
    if(b > a) a = b
    return a
})

console.log(max) //output: 345
```

That's all for now. Make sure to out check out my other articles.
{% user 0shuvo0 %}