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 的参数f
以reduceRight
使它们等效:
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
。这样,即使对于非交换关联运算,上述关系也成立。
所以,我的问题是:
reduceRight
以我的方式实施不是更有意义吗?- 为什么本机
reduceRight
没有按照我的方式实现?