rest 参数就是...收集多余的参数成一个真数组,代替 arguments。
核心规则:
① function fn(...args)——args 是真数组
② 必须放最后
③ 可以配合其他参数——function fn(a, ...rest)
坑:rest 是真数组能用数组方法、arguments 不是真数组、rest 只能有一个。
以前函数里想拿"传进来的所有参数",得用 arguments——它长得像数组(有 length、能按下标取),但其实是"类数组",map/filter/push 这些数组方法一个都用不了。
// 以前:arguments 是"类数组"
// 没写参数
function data() {
// 用 arguments 收全部实参
console.log(arguments);
}
// 传三个
data("大哥", "二哥", "三哥");
// {0:"大哥",1:"二哥",2:"三哥",length:3} —— 不是真数组!
// 现在:...args 直接给真数组
// ... 把所有实参打包成真数组
function data(...args) {
// ^^^^^ 把剩下的全部打包成数组
// 直接打这个真数组
console.log(args);
}
// 传三个
data("大哥", "二哥", "三哥");
// ["大哥","二哥","三哥"] ← 真数组,想怎么用怎么用
类数组 = 长得像数组、但 map/filter/push 全不能用,得先 Array.from(arguments) 转一遍。...args 给的是真数组,省了这一步。
参数列表里前面几个是"点名要的",... 永远收"别人挑剩下的"。
// 前两个参数 a、b 先被点名拿走,剩下的全进 rest
// a、b 点名拿前两个,...rest 收剩下的
function data(a, b, ...rest) {
// ↑ ↑ ^^^^^^^ 剩下的打包
// 只打剩下的
console.log(rest);
}
// 传四个
data("大哥", "二哥", "三哥", "四哥");
// ["三哥","四哥"] ← 前两个被 a、b 拿走,剩下两个进 rest
如果你把 ...rest 写在参数列表中间(比如 function f(a, ...rest, b)),浏览器会直接报错。因为它要收"剩下的",后面不能再有别的参数了——rest 必须永远放最后一位。
// 求一堆数的和(传几个都行)
// ...nums 把所有数收进真数组
function sum(...nums) {
// 累加器从 0 开始
let total = 0;
// nums 是真数组,直接 for...of
for (let n of nums) total += n;
// 返回总和
return total;
}
// 10
console.log(sum(1, 2, 3, 4));
// 拼成字符串:rest 是数组,join 直接用
// 收所有实参成真数组
function joinAll(...args) {
// 真数组才有 join
return args.join(" - ");
}
// 传三个
console.log(joinAll("A", "B", "C"));
// A - B - C
// 箭头函数里根本没有 arguments 这个变量 // 箭头函数只能用 rest 收参数 let data = (...args) => console.log(args); // ^^^^^^ 只能用 rest 收参数 // [1,2,3] data(1, 2, 3);
① 可能在什么地方用:写不定参数的工具函数(sum(...nums)、min(...nums))、事件回调里收全部参数、箭头函数里想拿全部参数(因为没有 arguments)。
② 常见的问题:把 ...rest 放中间导致语法报错;把 rest 和 arguments 混用;以为 rest 能拿到"已经点名的参数"。
③ 解决思路:rest 永远放最后;箭头函数里用 ...args 代替 arguments;需要全参数就一个 ...args,需要前几个就点名 + rest 组合。
| API | 作用 | 参数 | 返回值 | 代码示例 |
|---|---|---|---|---|
| ...rest | 把调用时多传的实参打包成一个真数组 | 必须放最后 | 一个真数组 | function sum(...rest) {} |