3

f对于array 元素的关联操作a,以下关系应该成立:a.reduce(f)应该等价于a.reduceRight(f)

事实上,它确实适用于关联和交换的操作。例如:

const a = [0,1,2,3,4,5,6,7,8,9];

const add = (a, b) => a + b;

console.log(a.reduce(add));
console.log(a.reduceRight(add));

但是,它不适用于关联但不可交换的操作。例如:

const a = [[0,1],[2,3],[4,5],[6,7],[8,9]];

const concat = (a, b) => a.concat(b);

console.log(JSON.stringify(a.reduce(concat)));
console.log(JSON.stringify(a.reduceRight(concat)));

我们需要翻转 for 的参数freduceRight使它们等效:

const a = [[0,1],[2,3],[4,5],[6,7],[8,9]];

const concat = (a, b) => a.concat(b);
const concatRight = (b, a) => a.concat(b);

console.log(JSON.stringify(a.reduce(concat)));
console.log(JSON.stringify(a.reduceRight(concatRight)));

这让我相信原生实现reduceRight是错误的。

我认为该reduceRight功能应实现如下:

var REDUCE_ERROR = "Reduce of empty array with no initial value";

Array.prototype.reduceRight = function (f, acc) {
    let { length } = this;
    const noAcc = arguments.length < 2;
    if (noAcc && length === 0) throw new TypeError(REDUCE_ERROR);
    let result = noAcc ? this[--length] : acc;
    while (length > 0) result = f(this[--length], result, length, this);
    return result;
};

由于result表示前一个值(右侧值),因此将其作为函数的第二个参数是有意义的f。当前值表示左侧值。因此,将当前值作为函数的第一个参数是有意义的f。这样,即使对于非交换关联运算,上述关系也成立。

所以,我的问题是:

  1. reduceRight以我的方式实施不是更有意义吗?
  2. 为什么本机reduceRight没有按照我的方式实现?
4

1 回答 1

4
于 2014-12-02T17:10:25.500 回答