Array.prototype.reduceRight()

Baseline 已广泛支持

此特性已相当成熟,可在许多设备和浏览器版本上使用。自 ⁨2015 年 7 月⁩以来,各浏览器均已提供此特性。

reduceRight() 方法用于 Array 实例,它从数组的右侧(从最后一个元素开始)对数组中的每个元素执行一个函数,并将累加器的结果作为下一次迭代的累加器传入,最终将数组归约成一个单一的值。

有关从左到右处理的说明,请参阅 Array.prototype.reduce()

试一试

const array = [
  [0, 1],
  [2, 3],
  [4, 5],
];

const result = array.reduceRight((accumulator, currentValue) =>
  accumulator.concat(currentValue),
);

console.log(result);
// Expected output: Array [4, 5, 2, 3, 0, 1]

语法

js
reduceRight(callbackFn)
reduceRight(callbackFn, initialValue)

参数

callbackFn

要对数组中的每个元素执行的回调函数。其返回值会成为下一次调用 callbackFnaccumulator 参数的值。对于最后一次调用,其返回值将成为 reduceRight() 的返回值。该函数会接收以下参数:

accumulator

上一次调用 callbackFn 所返回的值。第一次调用时,如果指定了 initialValue,则其值为 initialValue;否则其值为数组的最后一个元素。

currentValue

当前元素的值。第一次调用时,如果指定了 initialValue,则其值为数组的最后一个元素;否则其值为倒数第二个元素。

currentIndex

currentValue 在数组中的索引位置。第一次调用时,如果指定了 initialValue,则其值为 array.length - 1;否则为 array.length - 2

array

调用 reduceRight() 的数组。

initialValue 可选

作为第一次调用 callbackFn 的累加器的值。如果未提供初始值,则会使用数组的最后一个元素并跳过它。在空数组上调用 reduceRight() 且未提供初始值会抛出 TypeError

返回值

归约的结果值。

描述

reduceRight() 方法是一个迭代方法。它会按索引降序对数组中的所有元素运行一个“归约器”回调函数,并将它们累积成一个单一的值。有关这些方法通常如何工作的更多信息,请阅读迭代方法部分。

callbackFn 仅对具有已赋值的数组索引调用。对于稀疏数组中的空槽,它不会被调用。

与其他迭代方法不同,reduceRight() 不接受 thisArg 参数。callbackFn 总是以 undefined 作为 this 来调用,如果 callbackFn 是非严格模式,则会被 globalThis 替代。

reduceRight() 方法是通用的。它只期望 this 值具有 length 属性和整数键属性。

何时不使用 reduce() 中讨论过的关于 reduce 的所有注意事项同样适用于 reduceRight。由于 JavaScript 没有惰性求值语义,因此 reducereduceRight 之间没有性能差异。

示例

如何在没有初始值的情况下使用 reduceRight()

对 reduceRight callbackFn 的调用看起来会像这样

js
arr.reduceRight((accumulator, currentValue, index, array) => {
  // …
});

第一次调用函数时,accumulatorcurrentValue 可以是两种值之一。如果在调用 reduceRight 时提供了 initialValue,则 accumulator 将等于 initialValue,而 currentValue 将等于数组中的最后一个值。如果没有提供 initialValue,则 accumulator 将等于数组中的最后一个值,而 currentValue 将等于倒数第二个值。

如果数组为空且未提供 initialValue,则会抛出 TypeError。如果数组只有一个元素(无论位置如何)且未提供 initialValue,或者提供了 initialValue 但数组为空,则将返回该单个值,而不会调用 callbackFn

函数的一些示例运行流程如下

js
[0, 1, 2, 3, 4].reduceRight(
  (accumulator, currentValue, index, array) => accumulator + currentValue,
);

回调函数将被调用四次,每次调用的参数和返回值如下

accumulator currentValue index 返回值
第一次调用 4 3 3 7
第二次调用 7 2 2 9
第三次调用 9 1 1 10
第四次调用 10 0 0 10

array 参数在整个过程中始终不变——它始终是 [0, 1, 2, 3, 4]reduceRight 返回的值将是最后一次回调调用的值(10)。

如何在有初始值的情况下使用 reduceRight()

在这里,我们使用相同的算法来归约同一个数组,但将 10 作为 initialValue 传递给 reduceRight() 的第二个参数。

js
[0, 1, 2, 3, 4].reduceRight(
  (accumulator, currentValue, index, array) => accumulator + currentValue,
  10,
);
accumulator currentValue index 返回值
第一次调用 10 4 4 14
第二次调用 14 3 3 17
第三次调用 17 2 2 19
第四次调用 19 1 1 20
第五次调用 20 0 0 20

这次 reduceRight 返回的值将是 20

对数组中的所有值进行求和

js
const sum = [0, 1, 2, 3].reduceRight((a, b) => a + b);
// sum is 6

按顺序运行一个包含回调函数的异步函数列表,将每个函数的结果传递给下一个函数。

js
const waterfall =
  (...functions) =>
  (callback, ...args) =>
    functions.reduceRight(
      (composition, fn) =>
        (...results) =>
          fn(composition, ...results),
      callback,
    )(...args);

const randInt = (max) => Math.floor(Math.random() * max);

const add5 = (callback, x) => {
  setTimeout(callback, randInt(1000), x + 5);
};
const mul3 = (callback, x) => {
  setTimeout(callback, randInt(1000), x * 3);
};
const sub2 = (callback, x) => {
  setTimeout(callback, randInt(1000), x - 2);
};
const split = (callback, x) => {
  setTimeout(callback, randInt(1000), x, x);
};
const add = (callback, x, y) => {
  setTimeout(callback, randInt(1000), x + y);
};
const div4 = (callback, x) => {
  setTimeout(callback, randInt(1000), x / 4);
};

const computation = waterfall(add5, mul3, sub2, split, add, div4);
computation(console.log, 5); // Logs 14

// same as:

const computation2 = (input, callback) => {
  const f6 = (x) => div4(callback, x);
  const f5 = (x, y) => add(f6, x, y);
  const f4 = (x) => split(f5, x);
  const f3 = (x) => sub2(f4, x);
  const f2 = (x) => mul3(f3, x);
  add5(f2, input);
};

reduce 和 reduceRight 之间的区别

js
const a = ["1", "2", "3", "4", "5"];
const left = a.reduce((prev, cur) => prev + cur);
const right = a.reduceRight((prev, cur) => prev + cur);

console.log(left); // "12345"
console.log(right); // "54321"

定义可组合函数

函数组合是一种组合函数的方式,其中每个函数的输出都作为下一个函数的输入,最后一个函数的输出是最终结果。在此示例中,我们使用 reduceRight() 来实现函数组合。

有关函数组合的更多信息,请参阅 Wikipedia 上的函数组合

js
const compose =
  (...args) =>
  (value) =>
    args.reduceRight((acc, fn) => fn(acc), value);

// Increment passed number
const inc = (n) => n + 1;

// Doubles the passed value
const double = (n) => n * 2;

// using composition function
console.log(compose(double, inc)(2)); // 6

// using composition function
console.log(compose(inc, double)(2)); // 5

在稀疏数组中使用 reduceRight()

reduceRight() 会跳过稀疏数组中的缺失元素,但它不会跳过 undefined 值。

js
console.log([1, 2, , 4].reduceRight((a, b) => a + b)); // 7
console.log([1, 2, undefined, 4].reduceRight((a, b) => a + b)); // NaN

在非数组对象上调用 reduceRight()

reduceRight() 方法读取 thislength 属性,然后访问键是小于 length 的非负整数的每个属性。

js
const arrayLike = {
  length: 3,
  0: 2,
  1: 3,
  2: 4,
  3: 99, // ignored by reduceRight() since length is 3
};
console.log(Array.prototype.reduceRight.call(arrayLike, (x, y) => x - y));
// -1, which is 4 - 3 - 2

规范

规范
ECMAScript® 2026 语言规范
# sec-array.prototype.reduceright

浏览器兼容性

另见