Functions are first class citizens in JavaScript land. They can be treated like any other variable, which makes them a very powerful and indipensible part of the language. However, not everything was well thought out regarding functions, so there are some rough edges and annoyances that we coders have had to deal with. One of these is the way arguments are handled, epecially when there an indefinite number of arguments to deal with.
The Original Way
From JavaScript’s inception up through ES5, you can access a function’s arguments one of two ways: through the parameter names, or through the arguments object. The parameter names are the most straightforward and common way. Just specify the names that you would like the argument values to have, and they will be populated in order. It’s just like delcaring a variable
function iceCream( flavor, numberOfScoops, toppings ) {
// make ice cream here
}
iceCream( 'chocolate', 2, [ 'sprinkles', 'whipped cream' ] );
// flavor is 'chocolate'
// numberOfScoops is 2
// toppings is [ 'sprinkles', 'whipped cream' ]
For some more flexibility, JavaScript also provides the arguments object. It is an “array-like object”, meaning is has some of the properties of an array, but it is not an array. You can call .length on it, and you access its properties using numeric indexes starting from 0 (just like an array), but that’s all it has in common with an array. It comes in handy when you don’t know how many arguments you’re going to have, and it could be a large number. It is easily converted to a real array using Array.slice or Array.from, and that’s the most common use case.
function megaSundae() {
// convert arguments to a real array
var ingredients = [].slice.call(arguments);
// or
var ingredients = Array.from(arguments);
// now we can use any array methods we like
return ingredients.reduce(function( sundae, ingredient ) {
// add the ingredient to the sundae
}, {});
}
megaSundae('vanilla', 'chocolate', 'bananas', 'almonds', 'whipped cream');
As you can see, the arguments object is a bit awkward to deal with. There’s also one more obscure quirk with it that can bite you. If you are not in strict mode, and not using default, destructured, or rest parameters, changing the values in the arguments object also changes the corresponding parameter value, and vice-versa. It’s generally not good practice to change function parameter values, and also (as you will see) not good practice to use the arguments object, so this quirk is unlikely to affect you. However, this runs counter to how JavaScript works in all other contexts so it’s worth noting.
function iceCream( flavor ) {
console.log(flavor); // chocolate
console.log(arguments[0]); // chocolate
arguments[0] = 'vanilla';
console.log(flavor); // vanilla
console.log(arguments[0]); // vanilla
flavor = 'mint';
console.log(flavor); // mint
console.log(arguments[0]); // mint
}
iceCream('chocolate');
The Better Way
Starting with ES6, you can use the rest parameter syntax. It’s a way to collect all remaining parameters into a real array, with none of the drawbacks or oddities of the arguments object. I say all remaining parameters because you can pull out any number of parameters by name, and whatever’s left over goes into the rest parameter as an array. If there’s nothing left over, it’s just an empty array. And because it’s “the rest of the arguments”, it must be the last parameter.
function medals( gold, ...otherMedals ) {
console.log(gold);
console.log(otherMedals);
}
medals('🥇', '🥈', '🥉');
// 🥇
// [ '🥈', '🥉' ]
medals('🥇', '🥈');
// 🥇
// [ '🥈' ]
medals('🥇');
// 🥇
// []
medals();
// undefined
// []
If you want to collect all arguments into an array (like the arguments object, but a real array), you can use the rest parameter by itself.
function megaSundae(...ingredients) {
// no array conversion necessary!
return ingredients.reduce(function( sundae, ingredient ) {
// remaining code same as before
Key Differences
argumentsalways contains all parameters (including named parameters) whereas the...restparameter only contains parameters that have not been assigned names- Altering the
...restparameter array won’t affect other parameters, whereasargumentssometimes will (discussed above) - Arrow functions
() => {}do not have theargumentsobject, but can use the...restparameter
JavaScript is a living language, updated yearly by the TC39. As coders, we benefit from a large group of very smart people working hard to make it a better language for us to use. Rest paramters are one such improvement, and are clearly an advancement towards a cleaner, more usable, less buggy future.

