DEV Community

Cover image for ๐Ÿ‘จ๐Ÿปโ€๐Ÿ’ป UnderStand the Most Powerful ๐Ÿ’ช Function of Javascript
Kushal sharma
Kushal sharma

Posted on • Edited on

๐Ÿ‘จ๐Ÿปโ€๐Ÿ’ป UnderStand the Most Powerful ๐Ÿ’ช Function of Javascript

Hi, Dev Thanks for opening my blog. I hope you are doing well and ready to learn the most powerful function in the Javascript.

Why this is most powerful?

Yes this is the most powerful function this single function can do all the stuff of other array prototypes and this is worth sharing

So let's start

The reduce function executes a reducer function on each element of the array, resulting in single output value. The reducer is provided by the programmer.

How it works

Alt Text
The reduce method takes in 2 parameters.

First is the function passed to the reduce method that accepts four arguments.

Accumulator: It is the accumulated value previously returned in the last invocation of the callbackโ€”or initialValue if it was supplied. The reducer's returned value is assigned to the accumulator. The accumulator is remembered across each iteration throughout the array and ultimately becomes the final, single resulting value.

current Value: The value of the current element.

current Index: The index of the current element being processed in the array. It starts at index 0 if an initialValue is provided. Otherwise, it starts at index 1.

Source array: The array being iterated over

The second argument is A value to use as the first argument to the first call of the callback. If no initialValue is supplied, the first element in the array will be used as the initial accumulator value and skipped as currentValue. Calling reduce() on an empty array without an initialValue
will throw a TypeError. the initial value can be variable, array, object

Usages of Reduce

1) Sum of Array: Let's start with the basic one and then we will go deep inside the reduce

let sum = [0, 1, 2, 3].reduce(function (accumulator, currentValue) {
    console.log("accumulator is "+accumulator+ " and current value 
     is"+currentValue);
    return accumulator + currentValue;
})

as in the above code, you can see we have hasn't passed the initial value, so the accumulator value will be the first index(0) of the array and the current value will be the second one(1).
and the output will be

accumulator is 0 and current value is 1
accumulator is 1 and current value is 2
accumulator is 3 and current value is 3

Now let's give the initial value

let sum = [0, 1, 2, 3].reduce(function (accumulator, currentValue) {
    console.log("accumulator is "+accumulator+ " and current value 
     is"+currentValue);
    return accumulator + currentValue;
},5)

and see the output

accumulator is 5 and current value is 0
accumulator is 5 and current value is 1
accumulator is 6 and current value is 2
accumulator is 8 and current value is 3

I hope you understand how the accumulator and initial value works.

2) Make a new array from an existing array

suppose we have the array of JSON of students and we want to make a new array only with name and roll no. ofcouse you can do that with the loop or returning the new array with the Map, but in this, we are only going to use the reduce.

var students = [
    {
        name: "Kushal",
        class: "MCA",
        result: "Pass",
        mobileNo: "995481"
    },
      {
        name: "Rahul",
        class: "BCA",
        result: "Pass",
        mobileNo: "993281"
    },
      {
        name: "Kushal",
        class: "MCA",
        result: "Pass",
        mobileNo:"989481"
    }
];

const studentWithMobileNo = students.reduce((function(acc,student){
    return [...acc,{name:student.name,mobileNo:student.mobileNo}]
}),[])
console.log(studentWithMobileNo);

Here we initialized the accumulator with the empty array and then make a new array with the help of reducer function.

The output for the above will be

[
  { name: 'Kushal', mobileNo: '995481' },
  { name: 'Rahul', mobileNo: '993281' },
  { name: 'Kushal', mobileNo: '989481' }
]

Filtering the array

now suppose we only want to get only the pass records from the student's array, this can be done by a very simple method

const PassedStudents = students.reduce((function(acc,student){
     return student.result == "Pass" ?  [...acc,student] : acc
}),[])

You can do much more stuff with the Reduce, I hope that you like this post and understood the reduce function.
Thanks for reading โค โค and follow me to get updated when I post new blog

To keep up with everything Iโ€™m doing, follow me on Twitter. ==> Kushal Sharma

Top comments (18)

Collapse
 
jamesthomson profile image
James Thomson

While reduce is a highly useful function, both of these can be written with more appropriate functions that signify your intent.

Your first example could simply use map

const studentWithMobileNo = students.map(({name, mobileNo}) => ({ name, mobileNo }));

and your second with filter

const studentsThatPassed = students.filter(el => el.result === 'Pass');

Reduce would be more appropriate for something like tallying up the total class score or something like that.

const students = [
    {
        name: "Kushal",
        class: "MCA",
        result: "Fail",
        mobileNo: "995481",
        score: 1.5
    },
      {
        name: "Rahul",
        class: "BCA",
        result: "Pass",
        mobileNo: "993281",
        score: 2.9
    },
      {
        name: "Kushal",
        class: "MCA",
        result: "Pass",
        mobileNo:"989481",
        score: 3.6
    }
];

const totalScore = students.reduce((acc, val) => acc + val.score, 0);
Collapse
 
jpantunes profile image
JP Antunes

A better example of what you can do with reduce is group objects by property. Case in point, here's how to split the students by result:

students.reduce( (acc, val) => {
    !acc[val.result] 
        ? acc[val.result] = [val.name] 
        : acc[val.result].push(val.name); 
    return acc; 
}, {})

Produces:

{ Fail: [ 'Kushal' ], Pass: [ 'Rahul', 'Kushal' ] }
Collapse
 
jpantunes profile image
JP Antunes

Another interesting use case for reduce is to create a lookup table from an object and a property / key.

let phoneBook = students.reduce( (acc, val) => (acc[val.mobileNo] = val, acc), {})

> phoneBook[989481]
{ name: 'Kushal',
  class: 'MCA',
  result: 'Pass',
  mobileNo: '989481' }
Collapse
 
sharmakushal profile image
Kushal sharma

Aggred with you , i just want to show that you can also you reduce for map amd filter also

Collapse
 
jamesthomson profile image
James Thomson

I see... but why? Perhaps this is the disconnect in your article. Yes, you can use reduce to achieve other tasks, but why do so when there are more succinct functions? I mean, I could use a for loop for all of these as it's the basis of all these function, but I wouldn't do so unless I had good reason (performance can be one of those or the need to break out of the loop at any given time which you can't do with these).

The title of your article claims reduce is the most powerful javascript function (which is definitely debatable), but doesn't really explain or demonstrate why you say that. If using reduce were 5x faster than filter or map then the claim could be relevant, but that's not the case. I don't mean to be confrontational, hopefully you take this as a positive critique, I just don't see the correlation of your statement in the title of this article.

Thread Thread
 
digianpaul profile image
Paul DiGian

The point he is trying to make is that it is possible to implement filter and map in terms of reduce but it is not possible to do the inverse.

Indeed it is a well know theoretical fact.

Thread Thread
 
jamesthomson profile image
James Thomson

If that's the case, I don't think it comes across very well in the article. I understand reduce can be used in different ways, but so can many other things in JS. That doesn't mean they should be used this way. I'm not trying to degrade his article, I just think it's important to explain why you would do it this way or why it's interesting, but not something that should be practiced. There are a fair number of beginners (this article is even tagged with #beginner) on Dev.to and I think it's alarming to be encouraging a certain style of programming that would be torn apart in a code review.

Collapse
 
daksamit profile image
Dominik Aksamit

I definitely agree that reduce is a powerful build-in javascript function.
When you once understand how it works, it's hard to refrain from using it.
You can do a lot more than map values of an array, flat an array, or transform arrays into objects.
I see only one significant disadvantage - readability. Sometimes it could be hard to read for other developers what we mean using reduce function.

Here is a great explanation - youtube.com/watch?v=qaGjS7-qWzg

Collapse
 
sharmakushal profile image
Kushal sharma

Thanks for the youtube link

Collapse
 
jwp profile image
John Peters

Kushal, if we have these two functions doing the same thing.

let currentValue = 0;

if(useMap){
  //must have external value to reference
  numberArray.map(number=>{currentValue += numbers;});
} else {
  //whereas the same function using reduce, could be...
  numberArray.reduce(internalCurrentValue, number=>{internalCurrentValue+=number});
  currentValue = internalCurrentValue;
}

Do you know of other advantages of using reduce?

Collapse
 
ackmandesu profile image
AckmanDESU • Edited

Both of these are incorrect anyway.

  • Use .map when you want to modify the array you're looping over and return the result.
  • Use .forEach when you simply wanna loop over the values.
  • You put the reducing method as the second parameter of .reduce when it should be the first.

The reduce example should be written like this:

const result = numberArray.reduce((a, b) => a + b, 0);

Or slightly more readable:

const sum = (a, b) => a + b;
const result = numberArray.reduce(sum, 0);

And hell you could skip the second parameter (0) in this case as it would work regardless.

const sum = (a, b) => a + b;
const result = numberArray.reduce(sum);

So the complete example would be:


    const numberArray = [0, 1, 2, 3, 4, 5];
    const mode = 'xxx';
    let currentValue;

    switch (mode) {
        case 'for':
            for (let i = 0; i < numberArray.length; i += 1) {
                currentValue += numberArray[i];
            }
            break;
        case 'forEach':
            numberArray.forEach((number) => {
                currentValue += number;
            });
            break;
        case 'reduce':
            const sum = (a, b) => a + b;
            currentValue = numberArray.reduce(sum);
            break;
    }

As far as performance goes, the for loop is the fastest option. If you want readability this reduce example is pretty sweet, I'd use it. I believe for...of loops are somewhere in between regarding performance but I tend to avoid them.

Now, I believe reduce makes code hard to grasp most of the time, as 90% of its uses could be replaced by a different method. Since I stopped using Ruby my reduce usage has dropped considerably. Great for getting the sum of an array - probably bad for most other things.

Case in point, the example in the OP says:

    const passedStudents = students.reduce(
        (acc, student) => (student.result === 'Pass' ? [...acc, student] : acc),
        []
    );

But you could simply do this:

    const hasPassed = (student) => student.result === 'Pass';
    const passedStudents = students.filter(hasPassed);

I know it's simply to illustrate its usages but my point is it's harder to understand.

Collapse
 
jwp profile image
John Peters

Observation:
I was seeing the pattern of iterables and iterators. In C# the iterators would have just one name, with multiple overrides. This is why I asked about the distinction.

In JavaScript the forEach function would be the most fundamental built-in function to the array, with 'map' and 'reduce' and 'filter' giving (decorated) patterns of a fundamental iterator. All could be considered 'iterators'

Collapse
 
vjnvisakh profile image
Visakh Vijayan

Neat

Collapse
 
jozsefsallai profile image
Jรณzsef Sallai

No need to store an additional variable in the memory. Array.prototype.reduce is a bit slower though. So it's a question of memory management vs performance.

Collapse
 
lexlohr profile image
Alex Lohr

I believe there's a more powerful function in JS, which is String.prototype.replace. You can use it to replace static or even dynamic parts in strings or parse regular strings into arrays or objects:

let jar = {};
document.cookie.replace(/([^=; ]+)=([^;]+)/g, (_, key, val) => { jar[key] = val; });

You can even use it to do basic syntax highlighting of regular languages (might be a bit difficult with more recent ECMAscript versions): gist.github.com/atk/1084980

Now that's what I call powerful.

Collapse
 
vjnvisakh profile image
Visakh Vijayan

Very nicely explained. I will definitely put this to use :D
Please keep posting more stuff like these.

Collapse
 
gottz profile image
Jan-Stefan Janetzky

that tile feels clickbaity and completely opinionated.

Collapse
 
rohovdmytro profile image
Rohov Dmytro

I am wondering how I could not use it for the first years of programming.

What the hell I was doing? :) And, more important, how? :D