剩余参数
**rest 参数**语法允许函数将不定数量的参数作为数组接受,从而提供了一种在 JavaScript 中表示可变参数函数的方法。
试一试
语法
描述
函数定义的最后一个参数可以以 ...
(三个 U+002E FULL STOP 字符)为前缀,这会导致所有剩余的(用户提供的)参数被放置在一个Array
对象中。
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"]
rest 参数可以解构,这允许您忽略某些参数位置。
function ignoreFirst(...[, b, c]) {
return b + c;
}
但是,以下都是语法错误
function wrong1(...one, ...wrong) {}
function wrong2(...wrong, arg2, arg3) {}
function wrong3(...wrong,) {}
function wrong4(...wrong = []) {}
rest 参数不会计入函数的length
属性。
rest 参数和 arguments 对象的区别
rest 参数和arguments
对象之间存在三个主要区别
arguments
对象**不是真正的数组**,而 rest 参数是Array
实例,这意味着像sort()
、map()
、forEach()
或pop()
这样的方法可以直接应用于它。arguments
对象具有额外的(已弃用)callee
属性。- 在具有简单参数的非严格函数中,
arguments
对象将其索引与参数的值同步。当重新分配命名参数时,rest 参数数组永远不会更新其值。 - rest 参数将所有额外的参数捆绑到一个数组中,但不包含在
...restParam
之前定义的任何命名参数。arguments
对象包含所有参数——包括...restParam
数组中的参数——捆绑在一个类数组对象中。
示例
使用 rest 参数
在此示例中,第一个参数映射到 a
,第二个参数映射到 b
,因此这些命名参数按正常方式使用。
但是,第三个参数 manyMoreArgs
将是一个数组,其中包含第三个、第四个、第五个、第六个……第 n 个——用户指定的任意多个参数。
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
下面,即使只有一个值,最后一个参数仍然被放入数组中。
// 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
仍然是一个数组(尽管是一个空数组)。
// Using the same function definition from example above
myFun("one", "two");
// a, "one"
// b, "two"
// manyMoreArgs, [] <-- still an array
下面,只提供了一个参数,所以 b
获取默认值 undefined
,但 manyMoreArgs
仍然是一个空数组。
// Using the same function definition from example above
myFun("one");
// a, "one"
// b, undefined
// manyMoreArgs, [] <-- still an array
参数长度
由于 theArgs
是一个数组,因此其元素的数量由length
属性给出。如果函数的唯一参数是 rest 参数,则 restParams.length
将等于arguments.length
。
function fun1(...theArgs) {
console.log(theArgs.length);
}
fun1(); // 0
fun1(5); // 1
fun1(5, 6, 7); // 3
将 rest 参数与普通参数结合使用
在下一个示例中,rest 参数用于将第一个参数之后的所有参数收集到一个数组中。然后将收集到数组中的每个参数值乘以第一个参数,并返回该数组
function multiply(multiplier, ...theArgs) {
return theArgs.map((element) => multiplier * element);
}
const arr = multiply(2, 15, 25, 42);
console.log(arr); // [30, 50, 84]
从参数到数组
可以对 rest 参数使用Array
方法,但不能对 arguments
对象使用。
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)
引入 rest 参数是为了减少通常用于将一组参数转换为数组的样板代码。
在 rest 参数之前,需要在对 arguments
对象调用数组方法之前将其转换为普通数组
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)
}
现在,您可以使用 rest 参数轻松访问普通数组
function fn(...args) {
const normalArray = args;
const first = normalArray.shift(); // OK, gives the first argument
}
规范
规范 |
---|
ECMAScript 语言规范 # sec-function-definitions |
浏览器兼容性
BCD 表格仅在浏览器中加载