Featured image for “Harnessing the Javascript Spread Operator”

Harnessing the Javascript Spread Operator

September 21, 2023


Attention: The following article was published over 2 years ago, and the information provided may be aged or outdated. Please keep that in mind as you read the post.

The toolset of the JavaScript developer is ever-evolving and ever-changing. Array manipulation saw dramatic improvements in usability, utility, and readability with the release of the ECMAScript 6 standard in 2015. This update was released with game-changing features like arrow functions, scoped variables like ‘let’ and ‘const’, and many other commonly used tools.

As a developer, I use these features on a regular basis when developing in a Javascript environment, whether that’s a front-end library, such as React or Angular, or on the backend through Node. Most developers have experience with arrow functions and scoped variables, which are incredibly common to see throughout modern code bases. One feature included in ECMAScript 6 is the Spread Operator. While I do not often see it used, it is perhaps my favorite.

In this blog, I will cover the Spread Operator. We’ll talk about what it is and how it’s used to manipulate both objects and arrays. We’ll walk through some examples to help you get started using it in your programming along the way. Let’s jump in.

What is the Spread Operator?

The Spread Operator has several uses.

  1. It can be used as a shorthand for Javascript’s apply function.
  2. It can be utilized for creating deep copies of objects, and arrays.
  3. When creating a copy of objects and arrays, it can be used to modify properties or array entries of the copy at the declaration of the copy.

The Spread Operator is denoted by the use of an ellipses (...) in code:

const exampleObject = {key: "value"};
const spreadExampleObject = {...exampleObject};

The above code first declares a new JavaScript object with a genetically named Key property and an equally generic “value” string as the value. The second line uses the Spread Operator to create a new object based on the exampleObject from the line above.

If we examine the two objects using a console log, both should have the exact same key with the exact same value. Are they the same object though? No.

One is a deep copy of the other, and both can be manipulated without modifying the other. One of the biggest advantages of using the Spread Operator is saving time with redundant variable declarations!

What happens when we attempt to create a copy without the Spread Operator?

const exampleObject = {key: "value"};
const exampleObject2 = exampleObject;
exampleObject2.key = "new Value";
console.log(exampleObject.key);

What are we expecting the output of this console.log to be?

Spread Operator

We are logging the key of the first object: exampleObject, which was declared as “value” not “new Value”, so shouldn’t we be seeing “value” in the console log?

No, because even though we’re modifying the key for exampleObject2. exampleObject2 literally is exampleObject just referenced by a different name. If we use the Spread Operator when declaring exampleObject2 we are creating a deep copy instead of a reference (shallow copy).

const exampleObject = {key: "value"};
const exampleObject2 = {...exampleObject};
exampleObject2.key = "new Value";
console.log(exampleObject.key);

The output of this is:

exampleObject and exampleObject2 are completely different objects now, so modifying one does not modify the other.

Manipulating Objects

We can also use the Spread Operator to add new properties to a deep copied object, and we can do so without even declaring it as a new object. This is useful for feeding a deep copied object into a function as a parameter.

const exampleObject = {key: "value"};
const exampleObject2 = {...exampleObject, newKey: "New Value"};
console.log({...exampleObject2, x: "y"});

Output:

The same thing can be done with arrays:

const exampleArray = [1, 2, 3, 4];
const exampleArray2 = [...exampleArray];

These are two different arrays that contain the same content and can be modified independently of one another. Notice the difference between using the Spread Operator in an object declaration and an array declaration. An object used object brackets: {...sourceObject}, and an array used angle brackets [...sourceArray]. This is important and using the wrong one will result in errors.

Imagine you have a form on a page that’s loaded from the backend. When loading the form, you can use the Spread Operator to make a deep copy of the form’s data and drive the values of the form with the copy. Then, when the user is finished making changes to the form, you compare the original values of the loaded data to the deep-copied values to determine what has changed.

This is cool, and deep copies can be very useful, but why would you need an exact duplicate of an existing object/array if you weren’t wanting to modify it in some way? You probably wouldn’t, and the Spread Operator has your back! Let’s start with modifying a property on an object:

const person = {name: "Frank", age: 57, hobby: "Sportsball", occupation: "Door to door shoe salesman."};
const clone = {...person, name: "Roger"};
console.log(person.name);
console.log(clone.name);

Deep Copies using the Spread Operator

We have a person named Frank who is 57 years old and has other distinguishing features such as a single hobby and an occupation. We like the structure of this person/object, and technology allows us to clone people now. We’re gonna make a clone!

So we take the person (Frank) and use the Spread Operator to create a clone. We can’t have two Franks, though. Frankly, that would be confusing. So we change the name value to Roger during declaration.

We now have a person and their clone who have unique names despite one being based on one another. These two people can go off and do their own things now. What if you want to get wild and start modifying the properties of an object in more complex ways than just reassigning them? We can do that, too.

const person = {name: "Frank", age: 57, hobby: "Sportsball", occupation: "Door to door shoe salesman."};
const clone = {...person, age: person.age * 3};
console.log(clone);

The cloning science just isn’t there yet, and although we can create clones, they’re three times the age of the original person! Oh no!

With this example, we’re accessing one of the properties of the source object to help calculate the deep copied object. Here’s an example of modifying multiple properties at once:

const person = {name: "Frank", age: 57, hobby: "Sportsball", occupation: "Door to door shoe salesman."};
const clone = {...person, age: person.age * 3, favoriteIceCream: "vanilla"};
console.log(clone);

We’re even adding a property that didn’t exist on the original Frank! This is turning into a completely different person! Since we’re using the Spread Operator to make a deep copy, we’re not modifying the original Frank at all, so we can perform comparisons between the two objects. This might be useful when comparing a modified form value with its original value.

Manipulating Arrays

We can manipulate objects thanks to the Spread Operator, but what about arrays? Yep! We can do that, too. Let’s dive into an example.

const exampleArray = [1, 2, 3, 4];
const exampleArray2 = [...exampleArray, 4, 5];
console.log(exampleArray);
console.log(exampleArray2);

manipulating arrays with the Spread Operator in JavaScript

We added new elements to an existing array this, but we can also concat whole arrays, too.

const exampleArray = [1, 2, 3, 4];
const exampleArray2 = [5, 6, 7, 8];
const exampleArray3 = [...exampleArray, ...exampleArray2];
console.log(exampleArray3);

Let’s throw an object into this array as a declared deep copy of the original exampleArray! Now, let’s add a string into the same array as an undeclared copy and console log that out.

const exampleArray = [1, 2, 3, 4];
const exampleArray2 = [...exampleArray, {key: "object"}];
console.log([...exampleArray2, "dinner party"]);

But hold on, we can also modify arrays:

const exampleArray = [1, 2, 3, 4];
const exampleArray2 = [5, 6, 7, 8];
const exampleArray3 = [...exampleArray.filter(x => x !== 4), ...exampleArray2.filter(x => x %2 === 0)];
console.log(exampleArray3);

modifying arrays using the Spread Operator

This is useful because certain Javascript array functions such as filter() will not modify the original array, and instead, will expect you to create and declare a new array.

Let’s see how many lines recreating the above code block without the Spread Operator will require:

let exampleArray = [1, 2, 3, 4];
const exampleArray2 = [5, 6, 7, 8];
exampleArray = exampleArray.filter(x => x !== 4);
const filteredExampleArray2 = exampleArray2.filter(x => x %2 === 0);
const combinedExampleArrays = exampleArray.concat(filteredExampleArray2);
console.log(combinedExampleArrays);

Six lines without the Spread Operator, and only four with! I used a mixed example of reassigning a let variable and a declaration of a new const. The let of course was mutated and no longer has its original value.

Wrapping Up

The Spread Operator does a lot to reduce the amount of code written, and it is very useful when working with objects and arrays that need their original values to be maintained while requiring their values to be modified.

It’s been incredibly useful to me in my projects, and I am confident you will find similar results in your own work. So, get out there and spread the word about the Spread Operator!

Let me know what you think in the comments below! I would like to know how the Spread Operator has impacted your life. And as always, check out our Keyhole Dev Blog for more content like this.

About The Author

More From Alex Cassells

About Keyhole Software

Expert team of software developer consultants solving complex software challenges for U.S. clients.

Share This Post

Related Posts


Discuss This Article

Subscribe
Notify of
guest
0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments