1. ES6中数组新增了哪些扩展?
Rest 参数与 Spread 语法
在 JavaScript 中,很多内建函数都支持传入任意数量的参数。
例如:
Math.max(arg1, arg2, ..., argN)
—— 返回参数中的最大值。Object.assign(dest, src1, ..., srcN)
—— 依次将属性从src1..N
复制到dest
。- ……等。
在本章中,我们将学习如何编写支持传入任意数量参数的函数,以及如何将数组作为参数传递给这类函数。
Rest 参数 ...
在 JavaScript 中,无论函数是如何定义的,你都可以在调用它时传入任意数量的参数。
例如:
function sum(a, b) { return a + b; } alert( sum(1, 2, 3, 4, 5) );
虽然这里这个函数不会因为传入过多的参数而报错。但是,当然,只有前两个参数被求和了。
我们可以在函数定义中声明一个数组来收集参数。语法是这样的:...变量名
,这将会声明一个数组并指定其名称,其中存有剩余的参数。这三个点的语义就是“收集剩余的参数并存进指定数组中”。
例如,我们需要把所有的参数都放到数组 args
中:
function sumAll(...args) { // 数组名为 args let sum = 0; for (let arg of args) sum += arg; return sum; } alert( sumAll(1) ); // 1 alert( sumAll(1, 2) ); // 3 alert( sumAll(1, 2, 3) ); // 6
我们也可以选择将第一个参数获取为变量,并将剩余的参数收集起来。
下面的例子把前两个参数获取为变量,并把剩余的参数收集到 titles
数组中:
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 参数必须放到参数列表的末尾
Rest 参数会收集剩余的所有参数,因此下面这种用法没有意义,并且会导致错误:
function f(arg1, ...rest, arg2) { // arg2 在 ...rest 后面?! // error }
...rest
必须写在参数列表最后。
“arguments” 变量
有一个名为 arguments
的特殊类数组对象可以在函数中被访问,该对象以参数在参数列表中的索引作为键,存储所有参数。
例如:
function showName() { alert( arguments.length ); alert( arguments[0] ); alert( arguments[1] ); // 它是可遍历的 // for(let arg of arguments) alert(arg); } // 依次显示:2,Julius,Caesar showName("Julius", "Caesar"); // 依次显示:1,Ilya,undefined(没有第二个参数) showName("Ilya");
在过去,JavaScript 中不支持 rest 参数语法,而使用 arguments
是获取函数所有参数的唯一方法。现在它仍然有效,我们可以在一些老代码里找到它。
但缺点是,尽管 arguments
是一个类数组,也是可迭代对象,但它终究不是数组。它不支持数组方法,因此我们不能调用 arguments.map(...)
等方法。
此外,它始终包含所有参数,我们不能像使用 rest 参数那样只截取参数的一部分。
因此,当我们需要这些功能时,最好使用 rest 参数。
箭头函数没有 "arguments"
如果我们在箭头函数中访问 arguments
,访问到的 arguments
并不属于箭头函数,而是属于箭头函数外部的“普通”函数。
举个例子:
function f() { let showArg = () => alert(arguments[0]); showArg(); } f(1); // 1
我们已经知道,箭头函数没有自身的 this
。现在我们知道了它们也没有特殊的 arguments
对象。