Considere la siguiente matriz:
const books = [ { id: 1, name: 'A song of ice and fire', genre: 'Fantasy', author: { name: 'George RR Martin', birthYear: 1948, }, releaseYear: 1991, }, { id: 2, name: 'The lord of the rings', genre: 'Fantasy', author: { name: 'JRR Tolkien', birthYear: 1892, }, releaseYear: 1954, }, { ];Supongamos que quiero imprimir el libro con el título más largo. Los siguientes trabajos:
const longestBook = () => { const longestName = books.reduce((accumulator, book) => { if (book.name.length > accumulator.name.length) { return book; } return accumulator; }); return longestName } console.log(longestBook().name);Mi pregunta es, ¿por qué no puedo devolver book.name / accumulator.name directamente en lugar de usar .name solo al llamar a la función? Si trato de hacerlo, el resultado es indefinido.
const longestBook = () => { const longestName = books.reduce((accumulator, book) => { if (book.name.length > accumulator.name.length) { return book.name; } return accumulator.name; }); return longestName } console.log(longestBook());Si el acumulador se convierte en la propiedad .name , será una cadena simple y ya no tendrá una propiedad .name para comparar en la siguiente iteración.
Debería ser coherente con su tipo de acumulador desde el principio al proporcionar un valor inicial. Una cadena vacía sería suficiente...
return books.reduce( (acc, { name }) => name.length > acc ? name : acc, "" // initial value );Con reduce , está pasando un solo valor, el acumulador, de la iteración anterior a la iteración actual. En devoluciones de llamada reducidas estructuradas decentemente, el acumulador generalmente debe mantener la misma forma durante todo el ciclo, de modo que la lógica se pueda realizar en él de manera predecible y consistente.
Si intenta devolver solo el .name , hay problemas:
const longestName = books.reduce((accumulator, book) => { if (book.name.length > accumulator.name.length) { return book.name; } return accumulator.name; });porque
.name del primer objeto de libro o del segundo objeto de libro. El nombre es una cadena, por lo que esto da como resultado que el acumulador sea una cadena para la segunda iteración.return accumulator.name no devuelve nada.Estará acumulando una cadena en lugar de un objeto, por lo que todo el método reduce() debe estar orientado a eso.
Eso también significa que deberá proporcionar un valor inicial para reduce() . De forma predeterminada, toma el primer valor de la matriz, que es un objeto y no una cadena.
const books = [{ id: 1, name: 'A song of ice and fire', genre: 'Fantasy', author: { name: 'George RR Martin', birthYear: 1948, }, releaseYear: 1991, }, { id: 2, name: 'The lord of the rings', genre: 'Fantasy', author: { name: 'JRR Tolkien', birthYear: 1892, }, releaseYear: 1954, }]; const longestBook = () => { const longestName = books.reduce((accumulator, { name }) => { if (name.length > accumulator.length) { return name; } return accumulator; }, ''); return longestName; } console.log(longestBook());