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

瀏覽器相容性

另見