DEV Community

Cover image for Rest Parameters and arguments object: A Quick JavaScript Guide
Aleksandra Dudkina
Aleksandra Dudkina

Posted on • Originally published at aleksandradudkina.hashnode.dev

Rest Parameters and arguments object: A Quick JavaScript Guide

When I was learning JavaScript, rest parameters and the arguments object felt confusingly similar.

Here's a quick breakdown.

Why do we even need it

Imagine you're writing a function to calculate the total price of items in a shopping cart.

function calculateTotal(firstItemPrice, secondItemPrice, thirdItemPrice) {
  let total = 0;
  total = total + firstItemPrice + secondItemPrice + thirdItemPrice
  return total;
}

calculateTotal(10, 20, 30); // 60
Enter fullscreen mode Exit fullscreen mode

This works perfectly, except for the fact that it works perfectly only for 3 items. What if we need to calculate the price of 5 items? Or of 10 items? We really wouldn't want to pass 10 similar arguments to a function.. We don't even know how many items a user will put in a cart in the first place. And this is when the arguments object and rest parameters come in handy.

You need arguments object and rest parameters when you don't know how many parameters will be passed to a function in advance.

Arguments Object Usage

JavaScript gives us a built-in way to handle an unknown number of arguments - the arguments object. Think of it this way: it packs all the arguments you pass to a function inside just one variable.

// you don't need to declare arguments here
function calculateTotal() {
  let total = 0;

// all the parameters you pass are inside arguments
// let's iterate over all items to count their total price
  for (let i = 0; i < arguments.length; i++) {
    total += arguments[i];
  }

  return total;
}

calculateTotal(10, 20, 30);        // 60
calculateTotal(5, 15, 25, 35);     // 80
Enter fullscreen mode Exit fullscreen mode

Now we can count the total price of any number of items!

If you look carefully at the function we've just created you might want to use .reduce() here. Let's see how it'll work:

function calculateTotal() {
  return arguments.reduce((total, price) => total + price, 0);
}

calculateTotal(10, 20, 30);
// TypeError: arguments.reduce is not a function
Enter fullscreen mode Exit fullscreen mode

And this is exactly why arguments is so confusing.. We've just successfully iterated over it, we can even address any parameter with its index (for example, extract first item with arguments[0]) then why do we get this error?

If you try to use any other array method or iterator, you’ll run into the same error:

function calculateTotal() {
  arguments.forEach(price => {
    console.log(price);
  });
}

calculateTotal(10, 20, 30);
// TypeError: arguments.forEach is not a function
Enter fullscreen mode Exit fullscreen mode
function calculateTotal() {
  return arguments.map(price => price * 2);
}

calculateTotal(10, 20, 30);
// TypeError: arguments.map is not a function
Enter fullscreen mode Exit fullscreen mode

That’s because arguments is array-like, but NOT an actual array.

It supports:

  • numeric indexes (arguments[0])

  • length

But it doesn’t support:

  • array methods (map, reduce, forEach)

If you want to use arguments like an array, you first need to convert it into a real array with Array.from():

function calculateTotal() {
  const prices = Array.from(arguments);

  return prices.reduce((total, price) => total + price, 0);
}

calculateTotal(10, 20, 30); // 60
Enter fullscreen mode Exit fullscreen mode

At this point we:

  • received arguments

  • converted them into an array

  • and only then used array methods

We're also using additional memory by creating a new array.

It all feels like extra, unnecessary work for something so common.

If you already think that using arguments is not very convenient, let me give you more reason to doubt it:

arguments does NOT exist in arrow functions

const calculateTotal = () => {
  console.log(arguments);
};

calculateTotal(10, 20, 30);
// ReferenceError: arguments is not defined
Enter fullscreen mode Exit fullscreen mode

Arrow functions simply don’t have their own arguments object.

So if you try to handle a dynamic number of parameters in an arrow function, you can’t use arguments at all.

What we have for now:

Pros:

  • Can handle an unknown number of arguments

  • You can access any argument by its index (arguments[0])

  • You can check how many arguments were passed using arguments.length

Cons:

  • Not a real array: you need to convert it to an array first to use array methods like .map(), .reduce() or forEach

  • Converting to an array uses extra memory

  • Can't be used in arrow functions

And this is exactly why rest parameters exist.

Rest Parameters Usage

Rest parameters solve literally all the issues that arguments has.

Rest parameters let you collect all remaining function arguments into a real array right from the start.

const calculateTotal = (...prices) => {
  prices.forEach(price => {
    console.log(price);
  });
};

calculateTotal(10, 20, 30);
// 10
// 20
// 30
Enter fullscreen mode Exit fullscreen mode

Notice how:

  • We don't use arguments anymore

  • prices is already a real array

  • Works with any number of arguments, similarly to the arguments object

  • We can use rest parameters in an arrow function

There is even more advanced usage available - you can mix regular arguments with rest parameters:

// declare first argument separately
const calculateTotal = (firstItem, ...otherItems) => { 
 console.log(`First item purchased: ${firstItem}`);

    if (otherItems.length > 0) { 
        console.log("Other items purchased:"); 
        otherItems.forEach((item, index) => {
        console.log(`${index + 1}. ${item}`) 
      }) 
    } 
    else { 
        console.log("No other items purchased.")
    }
}

// Example usage with numbers as prices:
calculateTotal(50, 20, 15, 10);

// First item purchased: 50 
// Other items purchased:
// 20
// 15
// 10
Enter fullscreen mode Exit fullscreen mode

firstItem:

  • Captures the first argument separately

...otherItems :

  • Collects all remaining arguments into a real array

  • Allows iteration with .forEach(), .map(), .reduce(), etc.

Unlike the arguments object, which captures everything all together, rest parameters must always be the last argument in your function definition. function(a, ...b, c) will throw a SyntaxError:

// SyntaxError: Rest parameter must be last formal parameter 

function calculate(first, ...others, last) { 
    console.log(others); 
}

// How the JS engine sees it:
// "Okay, the first argument is 10. Then 'others' captures everything that's left. 
//  Then what am I supposed to put into 'last'? I'm confused!"
Enter fullscreen mode Exit fullscreen mode

If you want to separately use the last parameter, you can do it this way:

function calculate(first, ...others) { 
// using index to address the last parameter
    console.log(others[others.length-1]); 
}
Enter fullscreen mode Exit fullscreen mode

Don't confuse rest parameters with spread

Even though rest parameters (...args) and the spread operator (...myArray) use the same ... syntax, they do very different things.

Rest Parameters

  • Used in a function parameter list to collect all the arguments into a single array
function sum(first, ...others) {
  return others.reduce((total, num) => total + num, first);
}

sum(10, 20, 30, 40); // 100
Enter fullscreen mode Exit fullscreen mode

Here:

  • first = 10

  • ...others = [20, 30, 40] - collects remaining arguments into an array.

Spread Operator

  • Used when calling functions, creating arrays, or objects to expand elements.
const numbers = [20, 30, 40];
console.log(...numbers); // 20 30 40

const allNumbers = [10, ...numbers, 50];
console.log(allNumbers); // [10, 20, 30, 40, 50]
Enter fullscreen mode Exit fullscreen mode

Here ...numbers “spreads” the array elements into individual values. It does not collect anything - it expands.

Quick Rule of Thumb:

  • Rest parameterscollects multiple values into an array + used only in functions

  • Spread → expand an array into individual elements

Rest Parameters vs arguments key differences

Feature arguments Rest Parameters
Type Array-like Real array
Works in arrow functions No Yes
Modern usage Legacy Preferred
Supports array methods No Yes

The arguments object is a legacy feature from older versions of JavaScript. It can still be used. Rest parameters (...args) are a newer feature in JavaScript (ES6+), designed to replace most use cases of arguments. Use rest parameters by default.

Top comments (0)