The Spread Operator vs The Rest Pattern

Ever get confused with those three dots and where they’re supposed to go? Same. Let’s see what they’re all about and how and where to use them.

The Spread Operator

The spread operator is true to its name - it helps to spread things out. The spread operator is used where we would otherwise write values separated by commas.

For example, we have an array and we need to create another array that has all the elements of the first array.

const arr1 = [1, 2, 3]

const arr2 = [...arr1, 4, 5, 6] 

console.log(arr2) //output: [1, 2, 3, 4, 5, 6]

But that is just one instance. Let’s see how to use the spread operator with different data types.

Strings

When the spread operator is used on a string, it extracts the elements of the string and outputs them separately.

const ourStr = "This is a string example."

console.log(...ourStr) //output: T h i s   i s   a   s t r i n g   e x a m p l e .

When used on a string inside an array, it extracts the characters and turns them into elements of the array.

const ourStr = "This is another string"

const newArr = [...ourStr]

console.log(newArr) //output: ['T', 'h', 'i', 's', ' ', 'i', 's', ' ', 'a', 'n', 'o', 't', 'h', 'e', 'r', ' ', 's', 't', 'r', 'i', 'n', 'g']

Arrays

When the spread operator is used on arrays, it extracts the elements and displays them separately, the same way it does the string.

const numsArr = [34, 45, 56]

console.log(...numsArr) //output: 34 45 56

But when used on an array inside another array, as we saw in the first example, it creates a copy of the first array into the second one.

Objects

When the spread operator is used on an object, it also creates a copy of it.

const ourFirstObj = {firstName: "Lamisa", lastName: "Saadat"}

const anotherObj = {...ourFirstObj, profession: "Developer"}

console.log(anotherObj) // output: {firstName: "Lamisa", lastName: "Saadat", profession: "Developer"}

The Rest Pattern

The rest pattern on the other hand does the opposite of what the spread operator does - it collects elements and creates an array out of them. Let’s look at some use cases.

Functions

The rest pattern is used in functions as parameters when the number of arguments is unknown. This creates an array of the parameters and hence we can use array methods on them.

const add = function (...numbers) {
  let sum = 0;
  numbers.forEach(num => (sum += num));

  return sum
};

add(2, 3);
add(5, 3, 6, 3);
add(4, 5, 7, 3, 6, 8);

Since the rest pattern is used, any number of arguments can be provided to the function.

Rest parameters can also be passed into a function with regular parameters. Let’s look at an example.

const numbersList = function(num1, num2, ...numbers) {
    console.log(num1)
    console.log(num2)
    console.log(...numbers)
}

numbersList(20, 40, 4, 5, 7, 3, 6, 8); //20, 40, [4, 5, 7, 3, 6, 8]

It should be noted that only the arguments listed at the end are put into an array and the array methods can only be called this. It should also be noted that the rest parameter comes after all the parameters because it is also true to its name - these are the “rest” of the parameters.

Destructuring

The rest pattern is also heavily used in destructuring arrays and objects and it really comes in handy. Here’s how it looks:

//Destructuring an object
const {name, hobbies, ...otherInfo} = {name: "Lamisa", age: 30, occupation: "developer", drinkOfChoice: "coffee", hobbies: ["piano", "reading", "baking"]}

console.log(otherInfo) // {age: 30, occupation: "developer", drinkOfChoice: "coffee"}

//Destructuring an array
const [faveHobby, ...otherHobbies] = ["piano", "reading", "baking"]

console.log(otherHobbies) = ["reading", "baking"]

So using the rest pattern when destructing an object creates an object of all the properties not explicitly mentioned.

And destructuring an array creates an array of the rest of the elements in the array.

Hope this helped!