JavaScript中的reduce方法在对象数组上返回对象

9
我有一个对象数组,假设为 [{x:2, y:3}, {x:5, y:4}],我对其调用reduce((c, n) => c.y + n.y);。很明显这将返回7
然而,如果该数组只包含单个对象,比如[{x:2, y:4}],同样的reduce调用将返回该对象本身{x:2, y:4}
这是正常的行为吗?我是否需要在之后检查结果是对象还是数字?
5个回答

21
是的,当您没有为累加器传递一个初始值(您总是应该的)时,reduce 的正常行为就是这样。您的代码在除了那些具有两个对象的数组之外的任何数组上都无法按预期工作。
继续前进。
arr.reduce((acc, el) => acc + el.y, 0)

谢谢你的回答,我刚在 MDN 文档中看到了,我在检查时忽略了它。他们提供了一个使用 map() 的“防错”解决方案,但这会影响性能,不是吗? - Jo Colina
2
几乎没有什么明显的区别,使用你认为更容易理解的方式。你不需要使用 map,你可以将映射集成到你的 reducer 函数中。 - Bergi

5

当您不提供初始值(reduce的第二个参数)时,这是预期行为。来自MDN

如果数组为空且未提供initialValue,则会抛出TypeError。如果数组仅有一个元素(无论位置如何)且未提供initialValue,或者提供了initialValue但是数组为空,则该单个值将被返回,并且不会调用callback

它带有以下建议:

通常最好提供初始值,因为没有initialValue时有三种可能的输出。

因此,请按以下方式编写:

reduce((c, n) => c.y + n.y, { y: 0 });

4

这是因为 reduce 函数可以接收一个值作为默认值,如果不指定则取数组的第一个值。这也是为什么它可以用于多个值的原因。

但是,如果你这样做:

let a = [{x:5, y:4}].reduce((c, n) => c + n.y, 0);

console.log(a)

它正确地计算总和。


3

你是否将累加器初始化为{ y : 0 }

如果没有,它将返回原始对象。

let sum = data.reduce((c, n) => {
  return { "y" : c.y + n.y };
}, { y : 0 });

@Bergi 你是对的。已经修复了。现在累加器将始终是一个带有 y 键的对象。 - Sushanth --

2
注意:如果没有提供initialValue,则reduce将从索引1开始执行回调函数,跳过第一个索引。如果提供了initialValue,则从索引0开始。
如果数组为空且未提供initialValue,则会抛出TypeError。如果数组只有一个元素(无论位置如何)且未提供initialValue,或者提供了initialValue但数组为空,则将返回单个值而不调用回调函数。
通常最好提供初始值,因为没有initialValue会有三种可能的输出,如下例所示。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接