Translation: Liu Xiaoxi
Original link: css-tricks.com/understandi…
More articles can be read: github.com/YvetteLau/B…
For those of you who still don’t understand JavaScript’s Reduce method, let’s look at the following two pieces of code:
const nums = [1.2.3];
let value = 0;
for (let i = 0; i < nums.length; i++) {
value += nums[i];
}
Copy the code
const nums = [1.2.3];
const value = nums.reduce((ac, next) = > ac + next, 0);
Copy the code
These two pieces of code are functionally equivalent and are the sum of all the numbers in the array, but there are some conceptual differences between them. Let’s take a look at reducer first, because they are powerful and important in programming. There are hundreds of articles about Reducer, at last I will link the articles I like.
reducer
What is the
The first and most important point to understand about a Reducer is that it always returns a value. This value can be a number, string, array, or object, but it can always be just one. Reducer is good for many scenarios, but they are especially good for situations where a logic is applied to a set of values and a single result is ultimately achieved.
It should also be noted that reducer does not inherently change your initial values; Instead, they return something else.
Let’s review the first example so you can see what’s going on here, and take a look at the GIF below:
Viewing giFs may help us all, but back to the code:
const nums = [1.2.3];
let value = 0;
for (let i = 0; i < nums.length; i++) {
value += nums[i];
}
Copy the code
Array nums ([1,2,3]), the first value of each number in the array will be appended to value (0). We iterate over the number group and add each of its items to value.
Let’s try a different approach to this functionality:
const nums = [1.2.3];
const initialValue = 0;
const reducer = function (acc, item) {
return acc + item;
}
const total = nums.reduce(reducer, initialValue);
Copy the code
Now we have the same array, but this time we don’t change the initial value (the value in the previous code). Here, we have an initial value that we use only at the beginning. Next, we create a function that takes an accumulator (ACC) and an item (item). The accumulator is the cumulative value (or initialValue) returned in the previous call and is the input value for the next callback. In this case, you can think of it as a snowball rolling down a mountain, eating every value in its path as it grows by the size of every value it eats.
We will use.reduce() to receive this function and start with the initial value. You can use the arrow function shorthand:
const nums = [1.2.3];
const initialValue = 0;
const reducer = (acc, item) = > {
return acc + item;
}
const total = nums.reduce(reducer, initialValue);
Copy the code
To further shorten the code length, we know that the arrow function, without {}, defaults to return;
const nums = [1.2.3];
const initialValue = 0;
const reducer = (acc, item) = > acc + item;
const total = nums.reduce(reducer, initialValue);
Copy the code
Now we can apply this function where it is called, or we can set the initial value directly, as follows:
const nums = [1.2.3];
const total = nums.reduce((acc, item) = > acc + item, 0);
Copy the code
Accumulator can be a daunting term, so when we apply logic to callbacks, you can think of it as the current state of an array.
The call stack
If it’s not clear what happened, let’s document each iteration. The callback function used by Reduce runs for each item in the array. The following demonstration will help illustrate this point more clearly. I used a different array ([1,3,6]) because it can be confusing if the number is the same as the index.
const nums = [1.3.6];
const reducer4 = function (acc, item) {
console.log(`Acc: ${acc}, Item: ${item}, Return value: ${acc + item}`);
return acc + item;
}
const total4 = nums.reduce(reducer4, 0);
Copy the code
When we execute this code, we see the following output on the console:
Acc: 0, Item: 1, Return value: 1
Acc: 1, Item: 3, Return value: 4
Acc: 4, Item: 6, Return value: 10
Copy the code
Here’s a more intuitive breakdown:
- Accumulator (
acc
) from the initial value (initialValue
) : 0 - And then the first one
item
Is 1, so return value is 1 (0+1=1) - 1 becomes the accumulator the next time it is called
- Now our accumulator is 1(
acc
),item
The second entry is 3 - The return value becomes 4 (1+3=4)
- 4 becomes the accumulator on the next call, the next item on the call
item
Is 6 - The result is 10 (4+6=10), which is our final value because 6 is the last item in the array
A simple example
Now that we have this in hand, let’s look at some common and useful things that reducer can do.
How many X’s do we have?
Suppose you have an array of numbers and want to return an object that reports the number of occurrences of those numbers in the array. Note that the same applies to strings.
const nums = [3.5.6.82.1.4.3.5.82];
const result = nums.reduce((tally, amt) = > {
tally[amt] ? tally[amt]++ : tally[amt] = 1;
return tally;
}, {});
console.log(result);
/ / {' 1 ', 1, '3', 2 '4' : 1, '5', 2, '6' : 1, '82', 2}
Copy the code
Initially, we have an array and objects to put into it. In reducer, we first judge whether this item exists in the accumulator. If so, add 1. If it does not exist, add this entry and set it to 1. Finally, return the number of occurrences of each item. We then run the reduce function, passing both the reducer and the initial values.
Takes an array and converts it to an object that displays some criteria
Suppose we have an array and we want to create an object based on a set of conditions. Reduce is very applicable here! Now we want to create an object from any number item in the array and display both the odd and even versions of that number.
const nums = [3.5.6.82.1.4.3.5.82];
// we're going to make an object from an even and odd
// version of each instance of a number
const result = nums.reduce((acc, item) = > {
acc[item] = {
odd: item % 2 ? item : item - 1.even: item % 2 ? item + 1 : item
}
return acc;
}, {});
console.log(result);
Copy the code
Console output:
{ '1': { odd: 1.even: 2 },
'3': { odd: 3.even: 4 },
'4': { odd: 3.even: 4 },
'5': { odd: 5.even: 6 },
'6': { odd: 5.even: 6 },
'82': { odd: 81.even: 82}}Copy the code
As we iterate through each item in the array, we create an attribute for even and odd, and based on an inline condition with a modular operator, we either store the number or increment it by 1. Modular operators are great for this because they can quickly check for even or odd numbers — if it’s divisible by 2, it’s even, and if it’s not, it’s odd.
Other resources
At the top, I mentioned some other handy articles that will help you become more familiar with the Reducer role. Here are my favorites:
- The MDN documentation is very useful for this. Seriously, this is one of their best posts, and they also describe in more detail what happens if you don’t provide an initial value, which we didn’t cover in this post.
- Coding Train
- A Drip of JavaScript
Thank you for your precious time to read this article. If this article gives you some help or inspiration, please do not spare your praise and Star. Your praise is definitely the biggest motivation for me to move forward. Github.com/YvetteLau/B…