Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialJoseph Michelini
Python Development Techdegree Graduate 18,692 PointsWhy does my code still work without providing the .reduce() method an initialValue?
I was wondering why the code below is still working, in VS Code anyway, without providing the .reduce()
method an initialValue
. Should I have to for this to work?
const bookTitles = users
.map((user) => user.favoriteBooks.map((book) => book.title))
.reduce((arr, titles) => [...arr, ...titles]);
console.log(bookTitles);
My output is:
[
'The Iliad',
'The Brothers Karamazov',
'Tenth of December',
'Cloud Atlas',
'One Hundred Years of Solitude',
'Candide'
]
Thanks in advance!
2 Answers
Brandon White
Full Stack JavaScript Techdegree Graduate 35,763 PointsHi Joseph Michelini,
When you donβt provide the reduce method an initialValue, it uses the first element in the array as the accumulator on the first iteration, and skips the currentValue.
See here:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce#Syntax
Doron Geyer
Full Stack JavaScript Techdegree Student 13,897 PointsJoseph Michelini just as note on your question here, you should always add an initial value unless you have a very specific use case reason not to.
If initialValue is provided in the call to reduce(), then accumulator will be equal to initialValue, and currentValue will be equal to the first value in the array. If no initialValue is provided, then accumulator will be equal to the first value in the array, and currentValue will be equal to the second.
Note: If initialValue is not provided, reduce() will execute the callback function starting at index 1, skipping the first index. If initialValue is provided, it will start at index 0.
If the array is empty and no initialValue is provided, TypeError will be thrown.
If the array only has one element (regardless of position) and no initialValue is provided, or if initialValue is provided but the array is empty, the solo value will be returned without calling callback.
It is almost always safer to provide an initialValue, because there can be up to four possible output types without initialValue, as shown in the following example:
let maxCallback = ( acc, cur ) => Math.max( acc.x, cur.x );
let maxCallback2 = ( max, cur ) => Math.max( max, cur );
// reduce without initialValue
[ { x: 2 }, { x: 22 }, { x: 42 } ].reduce( maxCallback ); // NaN
[ { x: 2 }, { x: 22 } ].reduce( maxCallback ); // 22
[ { x: 2 } ].reduce( maxCallback ); // { x: 2 }
[ ].reduce( maxCallback ); // TypeError
// map & reduce with initialValue; better solution, also works for empty or larger arrays
[ { x: 22 }, { x: 42 } ].map( el => el.x )
.reduce( maxCallback2, -Infinity );
so in the first example. because you dont have an initial value set the value returned on the first run through causes the last run through to fail. Just as an example of what can go wrong.
Joseph Michelini
Python Development Techdegree Graduate 18,692 PointsJoseph Michelini
Python Development Techdegree Graduate 18,692 PointsThanks Brandon, for some reason I thought it would be returning strings in this case but it is in fact returning an array of arrays, setting the accumulator data type to an array like you mentioned. Thanks for your help!