简单Reduce函数-JavaScript

简单Reduce函数-JavaScript,javascript,ecmascript-6,reduce,Javascript,Ecmascript 6,Reduce,我在一个超级简单的数据集上使用reduce函数,我得到了NaN,结果出乎意料: let students = [{name: 'Leah', grade: 94},{name: 'Savannah', grade: 73},{name: 'Killian', grade: 38}]; let highest = students.reduce( (high, current) => Math.max(high.grade, current.grade) ) consol

我在一个超级简单的数据集上使用
reduce
函数,我得到了
NaN
,结果出乎意料:

let students = [{name: 'Leah', grade: 94},{name: 'Savannah', grade: 73},{name: 'Killian', grade: 38}];

let highest = students.reduce(
    (high, current) => Math.max(high.grade, current.grade)
    )

console.log(highest); // outputs NaN
奇怪的是,如果我将第一行更改为以下内容:(只需取出第三个对象)

然后它正确运行并输出94



为什么添加一个额外的对象会导致问题?

这一切都与累加器中的内容有关(
)。如果不向
reduce
提供第二个参数,累加器将作为第一个对象启动,当前元素是第二个元素。在第一次迭代中,将累加器视为对象,使用
high.grade
获取等级;然后返回一个数字(
94
),而不是一个对象,作为下一个累加器。在循环的下一次迭代中,
high
不再是一个对象,而是
94
,和
(94)。grade
没有意义

当您删除第三个元素时,没有第二次迭代,也没有时间让bug发生,您将获得当前累加器的值(
94
)。如果只有一个元素,您将获得初始累加器(
{name:'Leah',grade:94}
)。显然,这并不理想,因为您无法可靠地预测计算结果的形状(对象、数字或错误)

您需要决定是要数字还是对象,一个还是另一个

let highest = students.reduce(
    (high, current) => Math.max(high, current.grade),
    Number.NEGATIVE_INFINITY
)
此变量将累加器保留为一个数字,并将返回
94
。我们不能依赖默认的起始累加器,因为它需要是一个数字,所以我们人为地将它设置为
-INF

let highest = students.reduce(
    (high, current) => high.grade > current.grade ? high : current,
)

这是对象版本,其中
highest
{name:'Leah',grade:94}

结束。这里的问题是,第一次传递后的累加器(high)是一个数字(math.max返回的值),但每次传递都要求high是一个对象,grade是一个数字属性。因此,在第二次调用时,您正在调用
Math.max(未定义,73)
——它将返回
NaN
。相反,我建议使用
-Infinity
初始化累加器,并且只提供
高值

let highest=students.reduce(
(高,当前)=>数学最大值(高,当前,等级)

,-Infinity)

使用调试器逐步完成代码。每次通过循环,检查
当前
的值。你应该很快就能解决这个问题。谢谢你,你应该看到的。如果再添加一个对象,这个例子实际上会失败,我这样说对吗?(描述标题下的第一个示例)是的,如果添加另一个对象,它将返回NaN。您可以在控制台中轻松地进行测试以进行验证。@qarthandso对于描述下面的第一个示例,他们说您应该使用
.map
和初始值,而不是不带initialValue的
reduce()
示例。但他们也应该包括三个对象的失败案例;我相信这个例子正是为了警告这种情况(如果没有初始值,您需要非常小心,因为可能会出现几种不同的情况)。这个例子和你的完全一样。如果不指定初始值,则回调返回值的类型需要与第一个元素的类型匹配,否则会出现混乱。
let highest = students.reduce(
    (high, current) => high.grade > current.grade ? high : current,
)