TL; DR, defina o valor inicial
Usando desestruturação
arr.reduce( ( sum, { x } ) => sum + x , 0)
Sem desestruturação
arr.reduce( ( sum , cur ) => sum + cur.x , 0)
Com texto datilografado
arr.reduce( ( sum, { x } : { x: number } ) => sum + x , 0)
Vamos tentar o método de desestruturação:
const arr = [ { x: 1 }, { x: 2 }, { x: 4 } ]
const result = arr.reduce( ( sum, { x } ) => sum + x , 0)
console.log( result ) // 7
A chave para isso é definir o valor inicial. O valor de retorno se torna o primeiro parâmetro da próxima iteração.
A técnica usada na resposta principal não é idiomática
A resposta aceita propõe NÃO passar o valor "opcional". Isso está errado, pois a maneira idiomática é que o segundo parâmetro seja sempre incluído. Por quê? Três razões:
1. Perigoso
- Não passar o valor inicial é perigoso e pode criar efeitos colaterais e mutações se a função de retorno de chamada for descuidada.
Ver
const badCallback = (a,i) => Object.assign(a,i)
const foo = [ { a: 1 }, { b: 2 }, { c: 3 } ]
const bar = foo.reduce( badCallback ) // bad use of Object.assign
// Look, we've tampered with the original array
foo // [ { a: 1, b: 2, c: 3 }, { b: 2 }, { c: 3 } ]
Se, no entanto, tivéssemos feito dessa maneira, com o valor inicial:
const bar = foo.reduce( badCallback, {})
// foo is still OK
foo // { a: 1, b: 2, c: 3 }
Para o registro, a menos que você pretenda alterar o objeto original, defina o primeiro parâmetro de Object.assign
como um objeto vazio. Como esta: Object.assign({}, a, b, c)
.
2 - Melhor Inferência de Tipo
usar uma ferramenta como Typescript ou um editor como o VS Code, você obtém o benefício de informar ao compilador a inicial e ele pode detectar erros se você estiver fazendo errado. Se você não definir o valor inicial, em muitas situações, talvez não seja possível adivinhar e você poderá acabar com erros de tempo de execução assustadores.
3 - Respeite os Functors
- JavaScript brilha melhor quando seu filho funcional interno é liberado. No mundo funcional, há um padrão sobre como você "dobra" ou reduce
uma matriz. Quando você dobra ou aplica um catamorfismo à matriz, utiliza os valores dessa matriz para construir um novo tipo. Você precisa comunicar o tipo resultante - você deve fazer isso mesmo que o tipo final seja o dos valores na matriz, outra matriz ou qualquer outro tipo.
Vamos pensar de outra maneira. No JavaScript, as funções podem ser transmitidas como dados; é assim que os retornos de chamada funcionam; qual é o resultado do código a seguir?
[1,2,3].reduce(callback)
Ele retornará um número? Um objeto? Isso torna mais claro
[1,2,3].reduce(callback,0)
Leia mais sobre a especificação de programação funcional aqui: https://github.com/fantasyland/fantasy-land#foldable
Um pouco mais de experiência
O reduce
método usa dois parâmetros,
Array.prototype.reduce( callback, initialItem )
A callback
função aceita os seguintes parâmetros
(accumulator, itemInArray, indexInArray, entireArray) => { /* do stuff */ }
Para a primeira iteração,
Se initialItem
for fornecida, a reduce
função passa o initialItem
como o accumulator
e o primeiro item da matriz como o itemInArray
.
Se nãoinitialItem
for fornecida, a função passa o primeiro item da matriz como o e o segundo item da matriz, o que pode ser um comportamento confuso.reduce
initialItem
itemInArray
Eu ensino e recomendo sempre definir o valor inicial de reduzir.
Você pode verificar a documentação em:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
Espero que isto ajude!
arr.reduce(function(a,b){return a + b})
no segundo exemplo.