ES6+ 剩余参数
上节我们学习了展开语法,本节我们学习与之相反的操作 —— 剩余语法(Rest 也可以叫剩余参数)看起来和展开语法完全相同都是使用 ...
的语法糖,不同之处在于剩余参数用于解构数组和对象。从某种意义上说,剩余语法与展开语法是相反的:展开语法将数组展开为其中的各个元素,而剩余语法则是将多个元素收集起来成为整体。
在讲解剩余参数前,我们先来看看,剩余参数在参数中都了哪些问题?为什么会引入剩余参数的概念?
在 ES5 中,经常会传入不定参数,在传入不定参数时,ES5 的给出的案是通过 arguments
对象来时传递的参数。 arguments
对象不是数组,它是类数组对象,所谓类数组对象,就是指可以通过索引访问元素并且拥有 length 的对象。
简单的类数组对象是长这样的:
var arrLike = {
: 'name',
: 'age',
: 'job',
length:
}
而它所对应的数组应该是这样子的:
var arr = ['name', 'age', 'job'];
这里我们说类数组对象与数组的性质相似,是因为类数组对象在访问、赋值、长度上的操作与数组是一致的,具体可查阅相关的类数组使用。
在体中定义了 Arguments 对象,其包含的参数和其它,以 arguments
变量来指代。下面我们看个实例:
function fn() {
console.log(arguments);
}
fn('imooc', , 'ES6')
在控制台中打印出上面的结果,如下图所示:在定义的时候没有给定参数,但是通过 arguments
对象可以拿到传入的参数。可以看到 arguments
中包含了传递的参数、length 等,length 表示的是实参的长度,即的时候传入的参数个数。这样我们就对 arguments
对象有了一定的了解。
在 ES5 的开发模式下,想要使用传递的参数,则需要按位置把对应的参数取出来。尽管 arguments
是类数组且可遍历的变量,但它终究不是数组,它数组,因此我们不能 arguments.forEeach (…)
等数组的。需要使用一些特殊的转换成数组使用,如:
function fn() {
var arr = [].slice.call(arguments);
console.log(arr)
}
fn('ES6');
// ["ES6"]
fn('imooc', , 'ES6');
// ["imooc", 7, "ES6"]
终于借助 call
把 arguments
转化成真正的数组了。但是这样无疑是繁琐的过程,而且不容易理解。这时 ES6 给出了它的完美案 —— 剩余参数,那剩余参数是如何在传参中使用的呢?下面我们来看看实例:
function fn(...args) {
console.log(args)
}
fn('ES6');
// ["ES6"]
fn('imooc', , 'ES6');
// ["imooc", 7, "ES6"]
使用方式很简单在定义时使用 ...
紧接着跟收集的参数,这个收集的参数就是我们所传入不定参数的集合 —— 也就是数组。这样就很简单地摆脱了 arguments 的束缚。另外,还可以指定认的参数,如下示例:
function fn(name, ...args) {
console.log(name); // 基础参数
console.log(args); // 剩下的参数组成的数组
}
fn('ES6');
// 'ES6'
// []
fn('imooc', , 'ES6');
// "imooc"
// [7, "ES6"]
上面的中给第参数,声明变量 name,剩余的参数会被 ...
收集成数组,这就是剩余参数。引入剩余参数就是为了能替代内部的 arguments
,由于 arguments
对象不具备数组的,所以很多时候在使用之前要先转换成数组。而剩余参数本来就是数组,避免了这多余的一步,使用起来既优雅又自然。
ES6 允许按照一定模式,从数组和对象中,并对变量进行赋值,这被称为解构(下节我们会讲到)。 比如如下:
let array = [, , ]
let [a, b, c] = array;
console.log(a); // 1
console.log(b); // 2
console.log(c); // 3
再比如如下:
let obj = {a:, b:, c:}
let {a, b, c} = obj;
console.log(a); // 1
console.log(b); // 2
console.log(c); // 3
上面的两个例子,就是数组和对象的解构赋值过程,在解构赋值时,可以使用剩余操作符。剩余操作符所操作的变量会匹配在解构赋值中所有其他变量未匹配到的。看如下示例:
let {a, b, ...others } = {a: , b: , c: , d: , e: }
console.log(a); // 1
console.log(b); // 2
console.log(others); // {c: 3, d: 4, e: 5}
上面的中,a、b 会匹配对象中对应的值,...others
则会收集匹配余下的值,并打包起来构造新的对象赋值给了 others
。
数组也可以通过剩余操作符,把剩余的元素打包成新的数组赋值给剩余,如下:
let array = [, , , , ];
let [a, b, ...others] = array;
console.log(a); // 1
console.log(b); // 2
console.log(others); // [3,4,5]
在传参的时候也可以是和解构一起使用。如下所示。
function fun(...[a, b, c]) {
return a + b + c;
}
fun('1') // NaN (b 和 c 都是 undefined)
fun(, , ) // 6
fun(, , , ) // 6 多余的参数不会被到
上面的中,a、b、c 会去解构传入参数,有剩余语法的作用,对应的值从数组中的项解构出来,在内部直接使用解构出来的参数即可。剩余语法看起来和展开语法完全相同,不同点在于,剩余参数用于解构数组和对象。
本节结合了 ES5 中的 arguments
对象引入了为什么 ES6 会引入剩余参数的概念,可以看到剩余参数所带来的好处。本节可以总结以下几点: