Ready-made tools for common jobs
Finding the smallest value, the largest value and the total of an array are jobs you could do with a loop. JavaScript has built-in tools for them.
let prices = [4, 9, 2, 7];
console.log(Math.min(...prices)); // 2
console.log(Math.max(...prices)); // 9
let total = prices.reduce((sum, x) => sum + x, 0);
console.log(total); // 22
Math.min and Math.max
Math.min and Math.max compare separate numbers: Math.max(3, 8) is 8. They do not take an array. The three dots in ...prices are the spread syntax. They spread the array out into separate numbers, so Math.max(...prices) works like Math.max(4, 9, 2, 7).
Without the dots you pass the array itself, and the result is usually NaN ("not a number"). For the minutes array in this lesson, Math.max(minutes) gives NaN.
reduce for the sum
JavaScript has no sum function. The array method reduce does it. You give it an arrow function with two parameters, the running sum and the next value x. It returns the new sum. reduce calls it once per value, from left to right. The 0 after the function is the value the sum starts with.
To see what reduce does with the lesson's week of minutes, [25, 40, 15, 60, 30, 45, 20], here is the running sum and the next value each time the arrow function is called:
sum=0 x=25
sum=25 x=40
sum=65 x=15
sum=80 x=60
sum=140 x=30
sum=170 x=45
sum=215 x=20
After the last call the function returns 235, and that is the value reduce gives back. The first call starts from the 0 you passed in. This is the same bookkeeping as a loop with a total variable, written as a single expression. Whatever the arrow function returns becomes sum in the next call, so forgetting to return a value, for example by using curly braces without return, makes the next sum undefined. For [1, 2, 3] the whole result is then undefined instead of 6, which is an easy bug to miss when you only glance at the code. The shortest form, with no braces, returns the value automatically.
Empty arrays
An empty array has no smallest or largest value, and the built-ins do not raise an error. Math.max(...[]) is -Infinity and Math.min(...[]) is Infinity. They are strange numbers you may not notice, so check arr.length first when the array can be empty.
With reduce the start value matters. On an empty array, reduce with a start of 0 returns 0. Without the start value, it throws TypeError: Reduce of empty array with no initial value. So always pass the start value.
One more limit: the spread passes every value as a separate argument, and a very large array (hundreds of thousands of items) can fail with a RangeError: Maximum call stack size exceeded. For the small arrays in this chapter that never happens.
The lesson's task, step by step
minutes holds the minutes of coding practice on each day of a week: [25, 40, 15, 60, 30, 45, 20].
- Store the shortest day in
shortest:Math.min(...minutes). - Store the longest day in
longest:Math.max(...minutes). - Store the total in
total:minutes.reduce((sum, x) => sum + x, 0).
let minutes = [25, 40, 15, 60, 30, 45, 20];
let shortest = Math.min(...minutes);
let longest = Math.max(...minutes);
let total = minutes.reduce((sum, x) => sum + x, 0);
console.log("shortest = " + shortest);
console.log("longest = " + longest);
console.log("total = " + total);
The output is:
shortest = 15
longest = 60
total = 235
Key takeaways
Math.min(...arr)andMath.max(...arr)need the dots to spread the array.arr.reduce((sum, x) => sum + x, 0)adds the values up.- Empty arrays give
Infinityand-Infinityfrom the built-ins, so check the length first. - Always give
reducea start value.
