剩餘引數

Baseline 已廣泛支援

此特性已非常成熟,可在多種裝置和瀏覽器版本上使用。自 ⁨2016 年 9 月⁩以來,它已在各大瀏覽器中可用。

剩餘引數語法允許函式將不定數量的引數作為陣列接受,從而提供了一種在 JavaScript 中表示可變引數函式的方式。

試一試

function sum(...theArgs) {
  let total = 0;
  for (const arg of theArgs) {
    total += arg;
  }
  return total;
}

console.log(sum(1, 2, 3));
// Expected output: 6

console.log(sum(1, 2, 3, 4));
// Expected output: 10

語法

js
function f(a, b, ...theArgs) {
  // …
}

還有一些額外的語法限制

  • 一個函式定義只能有一個剩餘引數。
  • 剩餘引數必須是函式定義中的最後一個引數。
  • 剩餘引數後不允許使用尾隨逗號
  • 剩餘引數不能有預設值

描述

函式定義的最後一個引數可以加上字首...(三個U+002E句點字元),這將導致所有剩餘的(使用者提供的)引數被放置在一個Array物件中。

js
function myFun(a, b, ...manyMoreArgs) {
  console.log("a", a);
  console.log("b", b);
  console.log("manyMoreArgs", manyMoreArgs);
}

myFun("one", "two", "three", "four", "five", "six");

// Console Output:
// a, one
// b, two
// manyMoreArgs, ["three", "four", "five", "six"]

剩餘引數可以被解構,這允許你忽略某些引數位置。

js
function ignoreFirst(...[, b, c]) {
  return b + c;
}

但是,以下都是語法錯誤

js
function wrong1(...one, ...wrong) {}
function wrong2(...wrong, arg2, arg3) {}
function wrong3(...wrong,) {}
function wrong4(...wrong = []) {}

剩餘引數不計入函式的length屬性。

剩餘引數和 arguments 物件的區別

剩餘引數和arguments物件之間有四個主要區別

  • arguments物件不是真正的陣列,而剩餘引數是Array例項,這意味著諸如sort()map()forEach()pop()之類的方法可以直接應用於它。
  • arguments物件有一個額外的(已棄用的)callee屬性。
  • 在具有簡單引數的非嚴格函式中,arguments物件將其索引與引數值同步。當命名引數被重新賦值時,剩餘引數陣列永遠不會更新其值。
  • 剩餘引數將所有額外的引數打包成一個數組,但不包含在...restParam之前定義的任何命名引數。arguments物件包含所有引數——包括...restParam陣列中的引數——打包成一個類陣列物件。

示例

使用剩餘引數

在此示例中,第一個引數對映到a,第二個引數對映到b,因此這些命名引數像正常一樣使用。

但是,第三個引數manyMoreArgs將是一個數組,其中包含第三、第四、第五、第六、……、第n個引數——使用者指定多少個引數,就有多少個。

js
function myFun(a, b, ...manyMoreArgs) {
  console.log("a", a);
  console.log("b", b);
  console.log("manyMoreArgs", manyMoreArgs);
}

myFun("one", "two", "three", "four", "five", "six");

// a, "one"
// b, "two"
// manyMoreArgs, ["three", "four", "five", "six"] <-- an array

下面,即使只有一個值,最後一個引數仍然被放入一個數組中。

js
// Using the same function definition from example above

myFun("one", "two", "three");

// a, "one"
// b, "two"
// manyMoreArgs, ["three"] <-- an array with just one value

下面,沒有提供第三個引數,但manyMoreArgs仍然是一個數組(儘管是空的)。

js
// Using the same function definition from example above

myFun("one", "two");

// a, "one"
// b, "two"
// manyMoreArgs, [] <-- still an array

下面,只提供了一個引數,所以b得到預設值undefined,但manyMoreArgs仍然是一個空陣列。

js
// Using the same function definition from example above

myFun("one");

// a, "one"
// b, undefined
// manyMoreArgs, [] <-- still an array

引數長度

由於theArgs是一個數組,其元素的數量由length屬性給出。如果函式的唯一引數是剩餘引數,則restParams.length將等於arguments.length

js
function fun1(...theArgs) {
  console.log(theArgs.length);
}

fun1(); // 0
fun1(5); // 1
fun1(5, 6, 7); // 3

將剩餘引數與普通引數結合使用

在下一個示例中,剩餘引數用於將第一個引數之後的所有引數收集到一個數組中。然後將收集到陣列中的每個引數值乘以第一個引數,並返回該陣列。

js
function multiply(multiplier, ...theArgs) {
  return theArgs.map((element) => multiplier * element);
}

const arr = multiply(2, 15, 25, 42);
console.log(arr); // [30, 50, 84]

從引數到陣列

Array方法可以用於剩餘引數,但不能用於arguments物件

js
function sortRestArgs(...theArgs) {
  const sortedArgs = theArgs.sort();
  return sortedArgs;
}

console.log(sortRestArgs(5, 3, 7, 1)); // 1, 3, 5, 7

function sortArguments() {
  const sortedArgs = arguments.sort();
  return sortedArgs; // this will never happen
}

console.log(sortArguments(5, 3, 7, 1));
// throws a TypeError (arguments.sort is not a function)

引入剩餘引數是為了減少通常用於將一組引數轉換為陣列的樣板程式碼。

在剩餘引數之前,arguments需要轉換為普通陣列才能在其上呼叫陣列方法。

js
function fn(a, b) {
  const normalArray = Array.prototype.slice.call(arguments);
  // — or —
  const normalArray2 = [].slice.call(arguments);
  // — or —
  const normalArrayFrom = Array.from(arguments);

  const first = normalArray.shift(); // OK, gives the first argument
  const firstBad = arguments.shift(); // ERROR (arguments is not a normal array)
}

現在,你可以使用剩餘引數輕鬆訪問普通陣列。

js
function fn(...args) {
  const normalArray = args;
  const first = normalArray.shift(); // OK, gives the first argument
}

規範

規範
ECMAScript® 2026 語言規範
# sec-function-definitions

瀏覽器相容性

另見