为什么Array.prototype.reduce()不接受空数组作为累加器?

55

我正在尝试将数组中大于10的所有元素筛选到一个新的数组中。我有意不使用Array.prototype.filter(),因为我想学习reduce()方法。这是我正在尝试的代码:

var collection = [3, 5, 11, 23, 1];

// fileter all the elements bigger than 10 to a new array

var output = collection.reduce(function(filteredArr, collectionElemet) {
  if (collectionElemet > 10) {
    return filteredArr.push(collectionElemet);
  }
}, []);

我原本期望在第一次回调执行时,filteredArr被初始化为空数组,就像许多例子中提供的这里一样。但是当我运行这段代码时,我得到了错误 Cannot read property 'push' of undefined,我搞错了什么?谢谢!


如果条件为真 - 返回一个数字,如果不为真 - 返回undefined。 如果你只想过滤 - 使用 Array.prototype.filter,你当前的代码很丑陋和误导性。 - zerkms
1
@zerkms:这对于生产代码来说是公平的,但对于教育/实验来说不是。OP明确表示他知道filter,但正在尝试理解reduce - Amadan
2个回答

76
当你尝试执行return filteredArr.push(collectionElement)时,实际上是在推送操作后返回filteredArr的长度。push()方法将一个或多个元素添加到数组的末尾,并返回数组的新长度。 参考:Array.prototype.push()
你需要从匿名函数中返回filteredArr,以便它被用作下一次调用的previousValue
var collection = [3, 5, 11, 23, 1];

// filter all the elements bigger than 10 to a new array

var output = collection.reduce(function(filteredArr, collectionElement) {
  if (collectionElement > 10) {
    filteredArr.push(collectionElement);
  }
  return filteredArr;
}, []);

12

Array.prototype.push会返回新数组的长度。您需要返回累加器。一种简洁的方法是使用Array.prototype.concat,因为该方法实际上会返回数组:

var collection = [3, 5, 11, 23, 1];

var output = collection.reduce(function(filteredArr, collectionElemet) {
  if (collectionElemet > 10) {
    return filteredArr.concat(collectionElemet);
  }
}, []);

你需要返回累加器,这样下一次迭代就可以使用累加器的值。


不是我点的踩,但是 concat 每次都返回一个新数组,这很低效。push 是将新元素附加到现有数组的明显选择。 - RobG
2
并不总是关于效率,这个答案是有效的,因为它说明了两件事情:如何在一行中解决问题以及@segmentationfaulter必须返回filteredArr。他的困惑可能是认为filteredArr.push将返回filteredArr。 - titusfx

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