减少返回undefined?

时间:2016-03-14 02:54:04

标签: javascript

我有一个名为student的对象,有两个属性,名称和分数。我正在尝试使用得分属性执行计算,但我无法从学生阵列访问该属性。目前,我试图通过以下代码获得得分总和:

var sum = students.reduce(function(a, b) { 
                    return {sum: a.score + b.score}
                    })

这会返回一个未定义的值,并导致firefox中的显示怪异。我似乎无法找到错误。是否只能简单地访问参数,即var myVar = myArray.myObject.myProperty; ?

3 个答案:

答案 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语句中放置断点。当引擎停在那里时,检查 ab的值。或者,作为评论者建议,您可以在其中添加console.log行,以将值输出到控制台。在任何一种情况下,您都会看到它们是数组中的前两个值 - 如果您没有给它第二个参数,这就是reduce的行为方式。返回的值为{sum: students[0].score + students[1].score}。现在继续执行。您将在return声明中再次中断;再次检查ab。您将看到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/