What's the usage of rest parameter that will be added in ECMAScript 6?
For example, in ECMAScript 5 you can do the following to get an array of parameters starting from the second element:
// ES 5
store('Joe', 'money');
store('Jane', 'letters', 'certificates');
function store(name) {
var items = [].slice.call(arguments, 1); //['money'] in first case
items.forEach(function (item) {
vault.customer[name].push(item);
});
}
and that will be equivalent to the following code in ECMAScript 6:
// ES 6
store('Joe', 'money');
store('Jane', 'letters', 'certificates');
function store(name, ...items) {
items.forEach(function (item) {
vault.customer[name].push(items)
});
}
Is the difference between them is just syntax or there's a performance issue?
Also for spread operator (...)
//in ecmascript5
var max = Math.max.apply(null, [14, 3, 77]);
//but in ecmascript6
var max = Math.max(...[14, 3, 77]);
Is this just syntax change or performance issue?
A
rest
parameter will collect individual parameters into an array when you use the dots in a function parameter definition, while the spread operator expands an array into individual parameters when using the dots in afunction call
.When ever you want to collect individual parameters into an array, you would use
rest
operator in your function param definition.Dealing with
arguments
object inside nested function becomes really tricky, let's visit the below situation where our inner function needs access to thearguments
object passed.If our
inner function filterNumbers
needs access to arguments, it has to be stored above in avariable
before passing it further as each function has its ownarguments
object, which is an array like object.The approach works, but it's too verbose.
var args = arguments
can be omitted andArray.prototype.filter.call(args)
can be transformed toargs.filter()
using arest
parameter.When ever you want to expand an array into individual parameters, you would use spread operator in your function call.
In the above code, the spread operator will
“spread”
the array of three values across theparameters a, b, and c
. Thespread
operator can also expand an array to create individual elements in anarray
literal.Improved function invocation in ES6
ES5
provides.apply()
method on the function object to solve this. Unfortunately this technique has 3 problems:It seems irrelevant to indicate in
.apply()
second time the context countries making it more verbose.The
spread
operator fills thefunction
invocation arguments with values from anarray
. Let's improve the above sample with a spread operator:Spread
operator configures the constructor invocation arguments from an array, which is bit complicated and difficult directly when using.apply()
.Moreover you can combine multiple
spread
operators and regular arguments in the same invocation. The following example is removing from an array existing elements, then adds other array and an element:Clone an array instance:
otherWords
is a clone version of words array. Notice that cloning happens only on array itself, but not on the contained elements (i.e. it's not a deep clone).References: https://rainsoft.io/how-three-dots-changed-javascript/
Both, and more...
Rest parameters:
slice
).In addition to @kangax’s response, I would elaborate that performance and correctness are problematic many times the
arguments
object is invoked. If you pass thearguments
object to another function, you pass with it the right to modify the corresponding local variables in your scope.The existence of this feature invalidates local reasoning within a function, which makes JIT optimization more difficult and introduces certain security hazards. Programs that are designed for speed must work around this problem with far more elaborate boilerplate code than the
Array.prototype.slice.call(arguments)
idiom, and in security contexts, the passing ofarguments
must be strictly disallowed.Eliminating the need to use the
arguments
object to extract variadic arguments is one of the many advantages to the new syntax.I think the main differences in rest parameter are:
In your given example, you directly pass the object literal. Whilst still semantic, it seems un-analogous to the application of the spread operator. IMO, the spread operator's value becomes apparent when listing each parameter would determent code readability (and maintainability, when replacing traditional push, splice, concat methods).
With spread operator
ES6Fiddle demo (compiled by traceur-compiler)
Without spread operator
JSFiddle demo
In closing, I don't think that using the spread operator will improve or impede performance, it does however offer improved code readability, and arguably maintainability too. Regrettably, ES6 isn't widely implemented yet, and I'll assertively speculate that it will take sometime for browser support to ensue.
Fun fact: PHP 5.6 introduces similar functionality with its variadic functions which will make
func_get_args()
redundant.