添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

Rest 参数与 Spread 语法

在 JavaScript 中,很多内建函数都支持传入任意数量的参数。

  • Math.max(arg1, arg2, ..., argN) —— 返回参数中的最大值。
  • Object.assign(dest, src1, ..., srcN) —— 依次将属性从 src1..N 复制到 dest
  • 在本章中,我们将学习如何编写支持传入任意数量参数的函数,以及如何将数组作为参数传递给这类函数。

    Rest 参数 ...

    在 JavaScript 中,无论函数是如何定义的,你都可以在调用它时传入任意数量的参数。

    虽然这里这个函数不会因为传入过多的参数而报错。但是,当然,只有前两个参数被求和了。

    我们可以在函数定义中声明一个数组来收集参数。语法是这样的: ...变量名 ,这将会声明一个数组并指定其名称,其中存有剩余的参数。这三个点的语义就是“收集剩余的参数并存进指定数组中”。

    例如,我们需要把所有的参数都放到数组 args 中:

    function showName(firstName, lastName, ...titles) {
      alert( firstName + ' ' + lastName ); // Julius Caesar
      // 剩余的参数被放入 titles 数组中
      // i.e. titles = ["Consul", "Imperator"]
      alert( titles[0] ); // Consul
      alert( titles[1] ); // Imperator
      alert( titles.length ); // 2
    showName("Julius", "Caesar", "Consul", "Imperator");

    ...rest 必须写在参数列表最后。

    “arguments” 变量

    有一个名为 arguments 的特殊类数组对象可以在函数中被访问,该对象以参数在参数列表中的索引作为键,存储所有参数。

    在过去,JavaScript 中不支持 rest 参数语法,而使用 arguments 是获取函数所有参数的唯一方法。现在它仍然有效,我们可以在一些老代码里找到它。

    但缺点是,尽管 arguments 是一个类数组,也是可迭代对象,但它终究不是数组。它不支持数组方法,因此我们不能调用 arguments.map(...) 等方法。

    此外,它始终包含所有参数,我们不能像使用 rest 参数那样只截取参数的一部分。

    因此,当我们需要这些功能时,最好使用 rest 参数。

    箭头函数没有 "arguments"

    如果我们在箭头函数中访问 arguments ,访问到的 arguments 并不属于箭头函数,而是属于箭头函数外部的“普通”函数。

    举个例子:

    毫无疑问,我们不能手动地去一一设置参数 Math.max(arg[0], arg[1], arg[2]) ,因为我们不确定这儿有多少个。在代码执行时,参数数组中可能有很多个元素,也可能一个都没有。而且,这样的代码也很不优雅。

    Spread 语法 可以解决这个问题!它看起来和 rest 参数很像,也使用 ... ,但是二者的用途完全相反。

    当在函数调用中使用 ...arr 时,它会把可迭代对象 arr “展开”到参数列表中。

    Math.max 为例:

    Spread 语法内部使用了迭代器来收集元素,与 for..of 的方式相同。

    因此,对于一个字符串, for..of 会逐个返回该字符串中的字符, ...str 也同理会得到 "H","e","l","l","o" 这样的结果。随后,字符列表被传递给数组初始化器 [...str]

    对于这个特定任务,我们还可以使用 Array.from 来实现,因为该方法会将一个可迭代对象(如字符串)转换为数组:

    这种方式比使用 let arrCopy = Object.assign([], arr) 复制数组,或使用 let objCopy = Object.assign({}, obj) 复制对象来说更为简便。因此,只要情况允许,我们倾向于使用它。

    总结

    当我们在代码中看到 "..." 时,它要么是 rest 参数,要么是 spread 语法。

    有一个简单的方法可以区分它们:

  • ... 出现在函数参数列表的最后,那么它就是 rest 参数,它会把参数列表中剩余的参数收集到一个数组中。
  • ... 出现在函数调用或类似的表达式中,那它就是 spread 语法,它会把一个数组展开为列表。
  • 使用场景: