剩余参数(rest 参数)用于把多个剩余实参收集成一个数组

使用方式:函数中的最后一个参数写成 ...变量名

function myFunction(a, b, ...theRest) {
  // a 和 b 是独立的参数
  // theRest 是一个数组,包含了传入的所有其他参数
}

基本作用

它可以把前面已经匹配掉的参数之外,其余所有参数都收集起来。

function sum(...numbers) {
  return numbers.reduce((acc, curr) => acc + curr, 0)
}
 
sum(1, 2, 3, 4) // 10

这里的 numbers 就是一个真正的数组:

numbers // [1, 2, 3, 4]

使用规则

  • 只能写在参数列表的最后
  • 一个函数只能有一个剩余参数
  • 收集到的是一个真正的数组

错误写法:

function fn(...args, a) {}

因为剩余参数后面不能再有其他参数。

和 arguments 的区别

  • 是一个真正的数组,相较于argument对象更好用
  • 能用在所有函数,包括箭头函数
  • arguments 不是数组,只是类数组对象
  • 剩余参数语义更清晰,只收集“剩下的参数”
function fn(a, b, ...rest) {
  console.log(rest)
}
 
fn(1, 2, 3, 4) // [3, 4]

这里 ab 已经单独接收了前两个参数,rest 只负责后面的部分。

在 Function_bind 里是怎么用的

Function_bind 里有这样一段:

Function.prototype.myBind = function(context, ...args1) {
  const _this = this
 
  return function(...args2) {
    return _this.apply(context, [...args1, ...args2])
  }
}

这里有两组剩余参数:

  • ...args1:收集绑定时传入的参数
  • ...args2:收集新函数执行时传入的参数

例如:

const fn = log.myBind(student, "yui", "lzu")
fn("mio")

那么:

args1 // ["yui", "lzu"]
args2 // ["mio"]

最后再通过:

[...args1, ...args2]

合并成:

["yui", "lzu", "mio"]

这就实现了 bind 的“参数预置”效果。

rest 和 spread 的区别

虽然都写成 ...,但含义不同:

  • 写在函数参数里,是剩余参数(rest)
  • 写在数组/对象/调用表达式里,是扩展运算符(spread)
function fn(...args) {} // rest
 
const arr = [1, 2]
console.log([...arr, 3]) // spread

简单说:

  • rest:负责“收集”
  • spread:负责“展开”

常见使用场景

  • 不确定参数个数的函数
  • 替代 arguments
  • 手写 call / apply / bind
  • 函数柯里化、偏函数、工具函数封装

一句话总结

剩余参数就是把“多出来的参数”打包成数组,方便我们统一处理。

reference

argument对象 Function_bind 什么是rest参数