Simple zoom out function - JavaScript
I am working with a function reduce
on a super simple dataset and I get NaN
as a result when I was not expecting it:
let students = [{name: 'Leah', grade: 94},{name: 'Savannah', grade: 73},{name: 'Killian', grade: 38}];
let highest = students.reduce(
(high, current) => Math.max(high.grade, current.grade)
)
console.log(highest); // outputs NaN
It's weird if I change the first line to this: (just taking out the third object)
let students = [{name: 'Leah', grade: 94},{name: 'Savannah', grade: 73}];
then it runs correctly and outputs 94.
Why is adding an extra object causing problems?
source to share
It all has to do with what's in the battery ( high
). If you don't provide a second argument reduce
, the accumulator starts working as the first object and the current item as the second. In your first iteration, you treat the accumulator as an object, retrieve the score with high.grade
; but then you return a number ( 94
), not an object, to be your next accumulator. In the next iteration, the loop is high
no longer an object, but 94
rather (94).grade
does not make sense.
When you remove the third element, there is no second iteration and no time for error, and you will get the value of the current accumulator ( 94
). If there was only one item, you would get an initial accumulator ( {name: 'Leah', grade: 94}
). This is obviously not ideal, since you cannot reliably predict the shape of the result of your computation (object, number, or error).
You need to decide if you want a number or an object, one or the other.
let highest = students.reduce(
(high, current) => Math.max(high, current.grade),
Number.NEGATIVE_INFINITY
)
This option stores the accumulator as a number and returns 94
. We cannot rely on the default starter battery as it must be a number, so we artificially set it to -INF
.
let highest = students.reduce(
(high, current) => high.grade > current.grade ? high : current,
)
This is the version of the object where it highest
ends {name: 'Leah', grade: 94}
.
source to share
The problem is that the accumulator (high) after the first pass is a number (which is what math.max returns), but each pass requires the tall object to be an object with class as number property. So, on the second call, you call Math.max(undefined, 73)
- which will return NaN
. Instead, I recommend initializing the accumulator with -Infinity
and supplying only high
:
let highest = students.reduce(
(high, current) => Math.max(high, current.grade)
, -Infinity)
source to share