JavaScript is a very forgiving language. It’s easy to write code that runs but has mistakes in it.
In this article, we’ll look at why using the rest operators are better than their older alternatives.
Using Rest Parameters Instead of the arguments Object
Rest parameters are the best way to get all the arguments from a function. It works with all kinds of functions.
Whereas the old arguments
object only works with old-style traditional functions.
The rest operator is denoted by the ...
symbol in the function argument.
We can use it to put all arguments into an array or just arguments that haven’t been set as values of existing parameters that comes before the rest parameter expression.
For instance, if we have the following function:
const foo = (a, b, ...args) => console.log(a, b, args);
Then when we call it as follows:
foo(1, 2, 3, 4, 5);
We get that a
is 1, b
is 2, and c
is the array [3, 4, 5]
.
As we can see, the arguments that haven’t been set as the values of the parameters of the function are all put into an array which we can manipulate easily.
We can also put all arguments into an array by writing the following:
const foo = (...args) => console.log(args);
Then we get that args
is [1, 2, 3, 4, 5]
when we call it by writing foo(1, 2, 3, 4, 5);
.
As we can see, rest parameters works great with arrow functions. It works equally well with traditional functions.
This is much better than what we’re doing before, which is using the arguments
.
If we go back to using the arguments
, then we have to use traditional functions since arrow functions don’t bind to the arguments
object.
For instance, we’ve to define a function as follows to use it:
function foo() {
console.log(arguments);
}
Then we call it as follows:
foo(1, 2, 3, 4, 5);
We get:
Arguments(5) [1, 2, 3, 4, 5, callee: ƒ, Symbol(Symbol.iterator): ƒ]
in the console log output.
This is because the arguments
object isn’t an array. It’s an array-like iterable object.
All we can do is loop through it by its entry using the for
loop by its index as we do in the following code:
function foo() {
for (var i = 0; i < arguments.length; i++) {
console.log(arguments[i]);
}
}
As we can see, the arguments
object has a length
property, so we can loop through the entries by its index by using the brackets notation as we do with arrays.
We can also loop through with the for...of
loop since it’s an array-like iterable object. Therefore, we can write the following code:
function foo() {
for (const a of arguments) {
console.log(a);
}
}
However, we can’t do anything with it that an array can do like calling the map
or filter
method on it.
Most likewise, we’ve to convert the arguments
object to an array so we can do something with it. If we want to convert it to an array, then we have to do extra work to convert it to an array so that we can do more with it.
To do that we’ve to call the slice
method on an empty and then convert the this
that we used in slice to the arguuments
object so that it’ll return an array.
For instance, we can write the following code to convert the arguments
object to an array:
function foo() {
const args = [].slice.call(arguments, 0);
console.log(args);
}
In the code above, we converted the arguments
object into an array by calling the array prototype’s slice
method with the this
value set as arguments
so that it’ll return an array.
This works because the slice
method loops through the array to do the slicing. As we can see, we can loop through the argument
object with a regular loop since it has a length
property and we can access its values by its index.
We can also write the following instead of what we have in the previous example:
function foo() {
const args = Array.prototype.slice.call(arguments, 0);
console.log(args);
}
It does the same thing in that it calls the slice
array instance method, but using call
to change the this
inside the slice
method to the arguments
object.
If we come back to modern times, we can also use the spread operator to convert the arguments
object into an array as follows:
function foo() {
const args = [...arguments];
console.log(args);
}
Conclusion
Rest parameters is a useful feature in modern JavaScript. It lets us get the arguments of a function as an array. It’s much better than the old way with the arguments
object since it only works with traditional functions and we’ve to do work to convert it to an array.
The post JavaScript Best Practices — Rest Operator appeared first on The Web Dev.
Top comments (3)
Nice post, John, but sorry for being a bit pedantic -- this is syntax and the idea is best known as "rest parameters" (not to be confused with REST) according to MDN.
One example that often isn't shown that I'd like to share is in the use of recursive operations:
I think it's a great use of the rest syntax.
Anything is better than using
arguments
to get the arguments.Not necessary in JS, but this is very common in functional programming languages where loops constructs don't exist but all recursive calls are TCO (tail-call optimized)