如果没有给出初始值,则reduce方法会将累加器设置为数组的第一项

时间:2018-08-17 15:45:14

标签: javascript

尽管reduce函数的初始值为marked as optional,但是如果没有提供,则reducer会使用输入数组的第一项来初始化累加器。为什么呢?

const output = Object.keys({
  name: "david",
  age: 30
}).reduce((memo, key) => {
  return [...memo, key];
})

console.log(output);

// output: ["n", "a", "m", "e", "age"]

vs

const output = Object.keys({
  name: "david",
  age: 30
}).reduce((memo, key) => {
  return [...memo, key];
}, [])

console.log(output);

// output: ["name", "age"]

特定的代码示例仅是为了说明问题,我知道使用不带reduce的Object.keys会返回相同的结果。经过Chrome 68测试。

2 个答案:

答案 0 :(得分:1)

扩展运算符(...memo)将第一个值转换为字符数组。来自MDN

  

注意:如果未提供initialValue,则reduce()将执行   从索引1开始的回调函数,跳过第一个索引。如果   提供了initialValue,它将从索引0开始。

因此,没有初始值,您可以执行此操作。不是我认为更好,而是证明了所引用的行为

const output = Object.keys({
  name: "david",
  age: 30,
  shoesize: 45
}).reduce((memo, key, i) => (i < 2 ? [memo] : memo).concat(key));
//                           ^ so convert the first value to array
console.log(output);

答案 1 :(得分:1)

reduce可以递归定义,例如:

// <Except some details to do with empty slots>
Array.prototype.reduce = function(f, initial_value) {
    if (this.length === 0) {
        if (arguments.length > 1) {
            return initial_value;
        }
        throw TypeError('reduce of empty array with no initial value');
    }
    if (arguments.length > 1) {
        // Starting value given.
        const copy = this.slice();
        const first = copy.shift();
        return copy.reduce(f, f(initial_value, first));
    } else {
        // No starting value given
        // What should happen here?
        const copy = this.slice();
        const first = copy.shift();
        // return copy.reduce(f, f(intial_value, first));

        // Nothing was given as the initial_value.
        // What is the same as "nothing"?
        // Applying the function with an `identity` value
        // so that `f(identity, first) === first` means
        // that this `identity` is the same as nothing.

        // Of course, we can't know what that is if there
        // are no elements in the list, so we threw an error before.
        return copy.reduce(f, first);
    }
};

通常,reduce的第二个参数应该是该标识元素。对于像(a, b) => a + b这样的函数,应该是0。对于(a, b) => a * b,它将是1。对于(a, b) => Math.max(a, b),它将是-Infinity

对于您的功能,正如您正确编写的那样,它应该是[]

通常,初始值应为identity。因此,如果您不提供默认值,则reduce会继续,就好像您给它提供了函数的标识一样。

在您的情况下,它稍微复杂一些,因为如果您定义“等于”,那么该功能只有一个“标识”,这样(Input) x === (Output) [x]

有关更多信息,请参见the reduce function