DEV Community

Abin John
Abin John

Posted on • Originally published at abinjohn.in on

Introduction to JavaScript Spread Syntax & Rest Parameter

The Spread syntax and Rest parameter are two powerful concepts that were introduced to the JavaScript language with ES6 in 2015. At first glance, the two look similar, and developers who are just discovering the three dots often have a hard time figuring them out (I know I definitely did!)

Whenever we see ... in a code snippet, it is either spread or rest. So, what's the difference? and how are they useful?

The Spread Syntax

An iterable in JavaScript is an entity that can be looped over. An array is a good example. The spread syntax takes an iterable and "spreads" out its individual elements as comma-separated values.

Imagine we have an array called evenNums that contains a few even numbers and an array oddNums that contains a few odd numbers. We are tasked with creating a new array allNums that has all the numbers in oddNums followed by all the numbers in evenNums.

Here's the "traditional" way to do that -

const evenNums = [2, 4, 6];
const oddNums = [1, 3, 5];

const allNums = [oddNums[0], oddNums[1], oddNums[2], evenNums[0], evenNums[1], evenNums[2]];

Enter fullscreen mode Exit fullscreen mode

Here's what we are actually doing -

highlights comma-separated values in the code snippet

We are listing out each item of the array and separating them by commas. To create the allNums array, we do that for the oddNums array, add a comma, and then do the same for evenNums array.

Listing out the individual array elements separated by commas is exactly what the spread syntax does. Using the spread syntax, the code now becomes -

const allNums = [...oddNums, ...evenNums];

Enter fullscreen mode Exit fullscreen mode

Let's now revisit the definition: The spread syntax spreads out the iterable's contents and separates them by commas.

But what if we did this instead?

const allNums = [oddNums, evenNums]

Enter fullscreen mode Exit fullscreen mode

In this case, we are taking the two arrays and adding them as elements of allNums. We are not picking the individual elements. Here's what allNums would look like if we took the approach above.

const allNums = [oddNums, evenNums]

console.log(allNums) // [[1, 3, 5], [2, 4, 6]]

Enter fullscreen mode Exit fullscreen mode

Use cases

  1. Merge or concatenate arrays
    This is what we did in the example above. The spread operator is an easy and simple way to merge multiple arrays into one.

  2. Convert a string to an array
    A string is also an iterable. So by using the spread syntax, it can be easily converted to an array

    const string = 'JavaScript';
    
    const arrayFromString = [ ...string ];
    
    console.log(arrayFromString)
    // ["J", "a", "v", "a", "S", "c", "r", "i", "p", "t"]
    
  3. Create copies
    The spread syntax is a great way to create shallow copies of an iterable. Because of the way in which JavaScript handles different value types, simply assigning an array or object to a new value doesn't create a true copy [More on this here]. The spread syntax helps to spread the original array contents and put them in a new array.

  const baseArray = [1, 2, 3, 4];

  // Simply assigning baseArray to sameReference doesn't create a 
  copy.
  // They both point to the same location in memory.
  // Any change made to either will reflect in the other.
  const sameReference = baseArray;


  // shallowCopy contains the same items as baseArray,
  // but they don't point to the same memory location.
  // Any change made to either will not reflect in the other.
  const shallowCopy = [ ...baseArray ]

  baseArray.push(100)

  console.log(baseArray) //[1, 2, 3, 4, 100]
  console.log(sameReference) //[1, 2, 3, 4, 100]
  console.log(shallowCopy) //[1, 2, 3, 4]

Enter fullscreen mode Exit fullscreen mode

The Rest Parameter

If you've understood the spread syntax, Rest is easy (pun intended). Rest is the opposite of Spread i.e it takes comma-separated values and turns them into an array. This might be confusing at first, so let's quickly jump into an example.

Imagine we are destructring an array as shown below.

const [first, second, ...others] = [1, 2, 3, 4, 5, 6, 7, 8]

Enter fullscreen mode Exit fullscreen mode

Here's what logging the three variables to the console looks like.

console.log(first) // 1 
console.log(second) // 2
console.log(others) // [3, 4, 5, 6, 7, 8]

Enter fullscreen mode Exit fullscreen mode

Here's what happens behind the scenes -

demo of how variables get their values while destructuring

Both Rest and Spread use the same syntax: the three dots (... )

When the dots are used on an array, it spreads the array to its individual elements. It is called the spread syntax in such cases.

When the dots are used on a comma-separated list, it packs the list items into an array. It is called the rest pattern in such cases.

The rest pattern is popular with destructuring assignments like the one shown above, to pack the unwanted elements into an array. A more popular usage of rest is with function parameters. This is where the name 'Rest parameter' comes from as well.

Rest in function parameters

Here's a function that takes two numbers and prints their sum

 function printSum(num1, num2) {
    console.log(num1 + num2)
}

printSum(3, 5) // 8

Enter fullscreen mode Exit fullscreen mode

What if we wanted to make a more generalized function that can take any number of inputs and then print their sum? That's where rest comes in.

When we call a function with more than one argument, we pass the arguments as a comma-separated list within the function call's parenthesis.

printSum(1, 3, 4, 100);

Enter fullscreen mode Exit fullscreen mode

It is this comma-separated list that is passed to the function parameters. We can make use of the rest pattern to pack this comma-separated list into a single array.

As a first step, let's use the rest pattern to pack the items into an array and then log it to the console.

function printSum(...operands) {
    console.log(operands)
}

printSum(1, 3, 4 ,100) // [1, 3, 4, 100]

Enter fullscreen mode Exit fullscreen mode

Notice how the comma-separated list has now become an array

We can now use a loop to iterate over the operands array and print the sum. A for-of loop is used in the example below.

function printSum(...operands) {
  let sum = 0;
  for (const num of operands)
    sum += num;
  console.log(sum);
}

printSum(1, 3, 4, 100) // 108

Enter fullscreen mode Exit fullscreen mode

Such a function parameter that uses the spread syntax to pack incoming comma-separated items into a single array is called the rest parameter.

The rest parameter can be used in combination with regular parameters as well, but we have to be careful with two things

  1. The rest parameter should be the last parameter in the parameter list

    // INCORRECT
    function someFunction (a, ...rest, b) {
     //
    }
    
    // CORRECT 
    function someFunction (a, b, ...rest) {
     //
    }
    
  2. There should only be one rest parameter for a given function

    // INCORRECT
    function someFunction (a, ...rest, ...someMore) {
     //
    }
    
    // CORRECT 
    function someFunction (a, ...rest) {
     //
    }
    

Here's one final example. This function takes a greeting and a list of names, and prints out the greeting followed by the name for each name

function printGreeting(greeting, ...names) {
    for(const name of names)
        console.log(greeting + ', ' + name)
}

printGreeting("Hello", "John", "Doe", "Smith");
/*
Hello, John
Hello, Doe
Hello, Smith
*/

Enter fullscreen mode Exit fullscreen mode

Recap

  • Whenever we see ... in JavaScript, it is either spread or rest, depending on the usage.

  • When used on an array, it spreads the array elements into a comma-separated list.

  • When used on a comma-separated list, it packs all the items into an array.

  • The spread syntax is commonly used to merge arrays and make copies

  • Rest is commonly used in destructuring and also as a rest parameter in functions that need to accept an indefinite number of arguments.

I hope you got to learn something new today. If you did, do consider sharing this post. Got any questions? Comment away or connect with me on Twitter!

Top comments (0)