ES6之REST参数和扩展运算符

190 阅读3分钟

ES6中为我们加入了一种有趣语法,(...)在ES6中被称为扩展运算符,它可以对某个实现有iterator接口的对象进行展开运算,但是Object对象却不在这范围之内,这点确实给这种语法带来了很多不便,幸运的是,ES6开放了迭代接口的编写,所以我们可以弥补这个缺点,我在这一章中,本次主要分享(...)语法,下章再分享迭代的实现。

我们先来看看扩展运算符的使用例子。

//ES 5的写法
var str = "这里是一段中文!";
var first = [1, 2, 3];
var last = [4, 5, 6];
console.log(str.split("").join(" "))     //这 里 是 一 段 中 文 !
console.log(first.concat(last));       //[ 1, 2, 3, 4, 5, 6]
//ES 6的写法
let str = "这里是一段中文!";
let first = [1, 2, 3];
let last = [4, 5, 6];
console.log(...str);         //这 里 是 一 段 中 文 !
console.log([...first, ...last]);        //[ 1, 2, 3, 4, 5, 6]

我们看到ES6的扩展运算会把有迭代接口的对象进行逐个拆分开来,可能上面的例子不直观,感觉扩展运算符只是让我们少写了两个函数而已,现在我们来看看扩展运算符真实的威力!

//示例1:
let arr = [1];
let [first, ...last] = arr;
console.log(first, last);    //1, []
//示例2:
let arr = [1, 2, 3, 4, 5, 6];
let [,,,...last] = arr;
console.log(last);     //[4, 5, 6]
//示例3:
let user = { id : 1, name : 'test', roles : ['admin', 'test', 'dbAdmin'] };
let { roles : [,...role] } = user;
let { name : [...name] } = user;
console.log(role);     //['test', 'dbAdmin']
console.log(name);     //['t', 'e', 's', 't']

配合解构来使用扩展运算符,可以匹配取到我们想要的任何值,但是值得注意的是,我们扩展运算符是不能对Object进行操作的,比如:

let user = { id : 1, name : 'test', roles : ['admin', 'test', 'dbAdmin'] };
let result = { ...user }; //SyntaxError: Unexpected token ...

在上述示例1、示例2、示例3中的操作方式,被ES6称为逆运算,在逆运算中,值得注意的是,逆运算后面不能在有任何解构表示法,因为逆运算会将前者模式匹配出来的值放入到扩展运算中,如果后面还有解构模式或者逆运算,ES6不知道你前者逆运算是否是误写,例子如下:

//示例1:
let arr = [1, 2, 3, 4, 5, 6];
//报错,这种语法是矛盾的,如果first是arr所有的元素,则last取不到任何元素。
let [...first, ...last] = arr;
//示例2:
let arr = [1, 2, 3, 4, 5, 6];
//报错,道理是一样的,first匹配arr所有元素,则last匹配不到最后一个元素。
let [...first, last] = arr;

接下来,我们看看REST参数,ES6中(...)语法也允许在函数形参中使用,这种语法被称为REST参数,我们来看看REST参数使用。

//示例1:
function concat(...value){
        return value.join('');
}
concat("你","好",",","领","域", "!");      //你好,领域!
concat(4, 5, 6,);    //456
//示例2:
function push(me, ...args){
        return me.concat(args.join(''));
}
let result = push("你好",",","领","域","!");
console.log(result);      //你好,领域!
//示例3:
function max(a, b){
    return Math.max(a, b);
}
max(...[4, 6]);
//示例4:
function sum(a, b, c, d, e, f, g){
    return a + b + c + d + e + f + g;
}
sum(1, 2, ...[3, 4], 5, ..[6, 7]);

上述代码中,示例1、2是使用的REST参数,示例3、4是一般的扩展运算符,扩展运算符是允许将数组变为参数序列的,有一点很重要,REST参数也遵循上述规则,不能在REST参数后面有另一个REST参数或者形参,比如:

//报错,因为args会将所有形参第2个开始,合并在args里面,而...val是无法匹配的。
function push(me, ...args, ...val) {
}
//报错,同样的道理,第2个形参开始,组装到合并args里面,val是无法匹配的。
function push(me, ...args, val){
}