Rest操作符和Spread操作都是用三个点(...)表示,但作用整好相反。Rest操作符一般用在函数参数的声明中,而Spread用在函数的调用中。
下面看个例子:
'use strict';
function func(...args){
console.log(args);//[1,2,3,4]
}
func(1,2,3,4);
我们知道在strict mode下,对arguments做了很多限制,而且arguments是个arrayLike对象,不能像操作数组那样直接操作它。但用Rest操作符以后,args参数就是一个数组了,任何操作数组的方法都可以直接对args使用。
console.log(Object.prototype.toString.call(args));//[object Array]
在看个例子:
'use strict';
function f(x, ...y) {
console.log(x,y);//a,["b","c"]
}
f('a', 'b', 'c');
f('a')//x='1',y=[]
f()//x=undefined,y=[]
上面的两个例子都是把Rest操作符放在了函数形参的最后,那么,Rest操作符能不能应用在函数形参的其它位置呢?答案是:No
function f(x, ...y,z) {//Uncaught SyntaxError: Rest parameter must be last formal parameter
console.log(x,y,z);
}
f('a', 'b', 'c');
其实也很好理解,Rest单词的意思就是剩余的,把剩余的都归集到一起,所以上面的z形参就没什么作用了。但是我在ES6的规范(14.1 Function Definitions)中并没有找到这种语法错误。
在规范的13.3.3.6的最后有对函数参数中使用Rest操作的说明:
BindingRestElement : ... BindingIdentifier
1. Let lhs be ResolveBinding(StringValue of BindingIdentifier, environment).
2. ReturnIfAbrupt(lhs).
3. Let A be ArrayCreate(0).
4. Let n=0.
5. Repeat,
a. If iteratorRecord.[[done]] is false,
i. Let next be IteratorStep(iteratorRecord.[[iterator]]).
ii. If next is an abrupt completion, set iteratorRecord.[[done]] to true.
iii. ReturnIfAbrupt(next).
iv. If next is false, set iteratorRecord.[[done]] to true.
b. If iteratorRecord.[[done]] is true, then
i. If environment is undefined, return PutValue(lhs, A).
ii. Return InitializeReferencedBinding(lhs, A).
c. Let nextValue be IteratorValue(next).
d. If nextValue is an abrupt completion, set iteratorRecord.[[done]] to true.
e. ReturnIfAbrupt(nextValue).
f. Let status be CreateDataProperty(A, ToString (n), nextValue).
g. Assert: status is true.
h. Increment n by 1.
*以上全部代码在Chrome 47下通过测试