剩余参数

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

浏览器兼容性

另见