Rest and spread are two powerful JavaScript features introduced in ES6. These are two related features, primarily used with arrays and objects. While both of these features share the same syntax ...
, their functions are different. Let's take a look at each of them.
The rest operator
The rest operator allows us to pack elements or properties into an array or object. There are two primary use cases of the rest operator: in array and object destructuring and in a function parameter.
In array and object destructuring
Extracting a portion of an array or object when destructuring is one of the primary use cases of the rest operator.
// Extract a portion of an array
const numbers = [1, 2, 3, 4, 5];
const [first, ...restNumbers] = numbers;
console.log(restNumbers); // [ 2, 3, 4, 5 ]
// Extract a portion of an object
const person = {
name: 'John',
age: 30,
occupation: 'Software developer',
};
const { name, ...restPerson } = person;
console.log(restPerson); // { age: 30, occupation: 'Software developer' }
In the first example, we've destructured the numbers
array, creating two variables called first
and restNumbers
, where first
corresponds to the first element in the array, and restNumbers
is an array containing the remaining array elements.
In the second example, we've destructured the person
object, creating two variables called name
and restPerson
, where name
corresponds to the name property in the object, and restPerson
is an object containing the remaining object properties.
Notice that in both cases, we've used the rest operator to extract a portion of the array and object. This feature is particularly useful when we want to remove a few properties from an object.
Two important points regarding the rest operator when used in destructuring: it must be the last variable, and we can create a single variable using it in a destructuring assignment.
If you want to dive deep into array and object destructuring, I have an article on Understanding Array and Object destructuring in JavaScript that provides further insights.
In function parameter
The second use case of the rest operator is in function parameter, as shown in the following example:
function add(...numbers) {
console.log(numbers); // [ 2, 4, 8 ]
}
add(2, 4, 8);
In this example, we've used the rest operator in the function parameter. By doing so, any number of arguments provided to the add
function will be packed into an array, which is a flexible alternative to passing an array directly to the function.
Good to know that there is a difference between getting the arguments via the arguments
keyword and using the rest parameter. The arguments
keyword provides an array-like object, while the rest parameter creates a real array.
Also, the arrow function doesn't have the arguments
keyword, making the rest parameter a suitable alternative in such use cases.
The spread operator
The Spread operator allows us to unpack all the array elements and object properties. It is particularly useful to extend an array or object and to create shallow copies of them.
Some key points to remember regarding the spread operator:
- It works on all iterables and object.
- It won't copy a property if it already exists in the new object.
- It doesn't modify the original array or object; it creates a new one.
Extending array and object
Extending an array or object is one of the primary use cases of the spread operator.
// Extend an array
const numbers = [1, 2, 3];
const extended = [...numbers, 4, 5, 6];
console.log(extended); // [ 1, 2, 3, 4, 5, 6 ]
// Extend an object
const dev = {
occupation: 'Software developer',
isActive: true,
};
const john = {
name: 'John',
age: 30,
...dev,
};
console.log(john); // { name: 'John', age: 30, occupation: 'Software developer', isActive: true }
In these examples, we have used the spread operator to extend both the array and object. In the first example, we've created an extended
array with all the elements from the numbers
array. In the second example, we did the same, creating the john
object with all the properties from the dev
object.
Notice that in both cases, we've used the spread operator to copy all the elements from the array and properties from the object to another array and object.
Creating a shallow copy of an object
With the spread operator, we can create a shallow copy of an object.
const john = {
age: 30,
hobbies: ['Reading'],
};
const johnCopy = {
...john,
};
// Change john's age
john.age = 40;
// Add properties to hobbies array
john.hobbies.push('Coding');
console.log(johnCopy); // { age: 30, hobbies: [ 'Reading', 'Coding' ] }
In this example, we've created a john
object. Next, we've created the johnCopy
object by copying all the properties from the john
object in it using the spread operator.
Moving on in the code, we've updated john
's age
to '40' and added 'Coding' to the hobbies
array. Now, taking a look at the johnCopy
object, we can see that the age
is still '30', but the hobbies
array is updated and now contains both 'Reading' and 'Coding'.
This proves that the spread operator only truly copies the top-level properties in an object, not the nested arrays and objects. So, updating the nested arrays and objects will impact both the original and copied objects. This is an important behavior to be aware of.
This wraps up our discussion about the rest and spread operator in JavaScript. I hope you've learned a thing or two from this article. Feel free to share this article if you find the content useful.