我有一个名为student的对象,有两个属性,名称和分数。我正在尝试使用得分属性执行计算,但我无法从学生阵列访问该属性。目前,我试图通过以下代码获得得分总和:
var sum = students.reduce(function(a, b) {
return {sum: a.score + b.score}
})
这会返回一个未定义的值,并导致firefox中的显示怪异。我似乎无法找到错误。是否只能简单地访问参数,即var myVar = myArray.myObject.myProperty; ?
答案 0 :(得分:9)
我认为您不了解reduce
的工作原理。对于数组中的每个元素,它执行提供的函数。第一个参数是“累加器”;在访问每个元素时传递的东西(实际上,它是来自最后一个元素的函数的返回值,但它通常用作累加器)。第二个参数是被访问的元素。所以我认为你想要的是:
var sum = students.reduce(function(a, s) {
a.sum += s.score;
return a;
}, { sum: 0 });
当您调用reduce
时,您可以提供累加器的初始值(否则它将采用第一个元素的值,并且访问从第二个元素开始)。在这里,我们提供一个sum
属性设置为零的对象。
如果你想要的只是总和(不是具有sum
属性的对象),它可以更简单:
var sum = students.reduce(function(a, s) {
return a += s.score;
}, 0);
答案 1 :(得分:4)
要添加Ethan对reduce
的充分解释,您还可以将map
视为适当的格式,以便缩减为单个值。
students.map( student => student.score ).reduce( (a, b) => a + b, 0 );
答案 2 :(得分:2)
您的代码没有任何问题,一点调试都无济于事。在return
语句中放置断点。当引擎停在那里时,检查 a
和b
的值。或者,作为评论者建议,您可以在其中添加console.log
行,以将值输出到控制台。在任何一种情况下,您都会看到它们是数组中的前两个值 - 如果您没有给它第二个参数,这就是reduce
的行为方式。返回的值为{sum: students[0].score + students[1].score}
。现在继续执行。您将在return
声明中再次中断;再次检查a
和b
。您将看到a
不是学生,也不是数字,而是您在上一次迭代中返回的{sum: }
对象,它没有score
属性。假设前两个得分之和为192,则下一个返回值将为{sum: {sum: 192}.score + students[2].score}
。这变成了{sum: undefined + students[2].score}
,而NaN
变为undefined
,因为向NaN
添加任何内容都会返回a
。事情现在从那里走下坡路。
如果您发现第二次循环,{sum: 192}
为reduce
,您应该意识到这既不是您可以获得分数的学生,也不是您可以添加内容的值。通过对sum
文档的一些额外阅读,或许可以查看一些示例,您应该能够确定需要返回总和本身,而不是包含属性a
的对象。然后,该总和将成为循环的下一次迭代中的reduce
。为了完成这项工作,您需要将null
初始值0作为其第二个参数。
当你在编程过程中前进时,你会遇到很多这样的障碍。不幸的是,你不能依赖SO人来为你解决所有这些问题,即使他们这样做了,你可能会坚持几个小时或几天直到他们回答。你真的需要学习如何为自己确定并解决这些问题。调试器是这样做的关键,因此除了学习如何启动它,设置断点和检查变量之外别无选择。从您的日程安排中抽出几个小时,仔细阅读文档。您可以在https://developers.google.com/web/tools/chrome-devtools/找到它们。这里是一个很好的概述如何调试小程序; http://ericlippert.com/2014/03/05/how-to-debug-small-programs/