Search code examples
javascriptecmascript-6ecmascript-harmony

Usage of object destructuring in Array.reduce


I was trying to solve another person's problem on SO using Array.prototype.reduce and ...object destructuring. I don't understand why it works as expected when I'm using Object.assign, but not when using the spread operator.

const str = 'Jack:13,Phil:15,Lucy:12'

const arr = str.split(',')

let reducer = (acc, val) => {
  return { ...acc,
    ...{
      [val.split(':')[0]]: Number(val.split(':')[1])
    }
  }
}

let reducer2 = (acc, val) => {
  return Object.assign(acc, {
    [val.split(':')[0]]: Number(val.split(':')[1])
  })
}

let obj = {
  Jody: 29
}

let obj2 = {
  Julie: 28
}

arr.reduce(reducer, obj)
arr.reduce(reducer2, obj2)

console.log(obj)
/* output:
{
  "Jody": 29
}
*/
console.log(obj2)
/* output:
{
  "Julie": 28,
  "Jack": 13,
  "Phil": 15,
  "Lucy": 12
}
*/


Solution

  • Array reduce is often used to return a new value. Even if it mutates an accumulator, it's safe to assume that it can return a new value.

    arr.reduce(reducer, obj) relies on that obj is mutated. reducer2 mutates original object indeed, this is the reason why it works. But this contradicts with reducer which keeps an accumulator immutable.

    It should be:

    obj = arr.reduce(reducer, obj);