The Spread Operator

JavaScript ECMAScript 2024 · ✓ verified by execution on

The Illusion of Copying

When working with arrays in JavaScript, you will often find yourself needing to create a duplicate of an existing array. Perhaps you want to modify a list of names without permanently changing the original list, or perhaps you want to preserve a historical record of your data before applying a series of transformations.

However, a very common misconception among developers learning JavaScript is assuming that the equals sign (=) creates a brand new copy of an array. In reality, arrays in JavaScript are treated as reference types. When you assign an existing array to a new variable, you are not actually copying the contents of the array into a new space in memory. Instead, you are simply copying the reference (the address or pointer) to the exact same array in memory. Both variables now point to the identical location. If you modify one, you inadvertently modify the other. Let’s observe this dangerous behavior in action.

javascript
const original = [1, 2, 3];
const fakeCopy = original;
fakeCopy.push(4);
console.log(original);
Output
[ 1, 2, 3, 4 ]

As you can see from the output, even though we pushed the number 4 to fakeCopy, the original array was also modified! This side effect is the root of many bugs.

Memory Diagram: References vs Copies

Here is a visual representation of how a shallow copy creates a completely new array structure in memory, while assigning the reference just points a new variable name to the same existing box.

Reference Copy (fakeCopy) original fakeCopy [1, 2, 3] Spread Copy (realCopy) original [1, 2, 3] realCopy [1, 2, 3]
Assignment copies the reference, so both names point at one array. The spread operator builds a genuinely new array, which is why only the second is safe to modify.

The Spread Operator to the Rescue

To solve this problem and safely clone our data, JavaScript introduced a powerful feature in ES6 called the Spread syntax. It is represented by three consecutive dots (...).

The spread syntax effectively unpacks or “spreads out” an iterable object (like an array) into its individual elements. When you place the spread operator inside a new set of square brackets [], JavaScript takes all the individual items from the original array and drops them into a completely new array literal. This creates a true, independent copy in memory. Modifying the new array will no longer have any impact on the original array, allowing you to manipulate your data with confidence.

javascript · visualize
const original = [1, 2, 3];
const realCopy = [...original];
realCopy.push(4);
console.log(original);
console.log(realCopy);

Merging Multiple Arrays Together

The spread operator isn’t just useful for cloning single arrays; it is also the most modern and elegant way to combine multiple arrays together. Because the spread operator unpacks elements, you can use it multiple times within the same array literal.

Imagine you have two separate lists of seasonal items that you want to merge into a single master list. Instead of writing complex loops or using older methods like concat(), you can effortlessly place them side by side using the spread syntax.

javascript
const cold = ['Winter'];
const warm = ['Spring'];
const seasons = [...cold, ...warm];
console.log(seasons);
Output
[ 'Winter', 'Spring' ]

Adding New Elements On the Fly

The flexibility of the spread operator extends even further. Not only can you merge arrays, but you can also mix spread arrays with individual, hardcoded elements. You can seamlessly inject items at the beginning, in the middle, or at the end of the new array.

By inserting spread elements in the middle of a new array literal alongside newly defined values, you can build up complex arrays dynamically and cleanly.

javascript
const arr = [2, 3];
const newArr = [1, ...arr, 4];
console.log(newArr);
Output
[ 1, 2, 3, 4 ]

Beyond Arrays: Spreading Objects

While we have focused primarily on arrays, it’s worth noting that the spread operator is extremely versatile and works with other data structures as well. For example, it is just as common to use the spread syntax on object literals.

In an object literal, the spread syntax enumerates the properties of an object and adds the key-value pairs to the newly created object. This allows you to clone objects or merge multiple objects together just as easily as we did with arrays.

javascript
const obj = {a: 1};
const copy = {...obj, b: 2};
console.log(copy.b);
Output
2

A Note on Shallow Copies

There is one extremely important detail you must understand about the spread operator: it only creates a shallow copy.

Spread syntax effectively goes one level deep. It copies the top-level elements of the array. But what happens if your array contains other arrays, or if it contains objects? In that scenario, the spread operator copies the references to those nested items, rather than duplicating the nested items themselves. Therefore, if you mutate a deeply nested object inside your cloned array, the change will reflect in the original array. Keep this in mind when working with multidimensional data.

Predict the output javascript

Read the code. What exactly will it print? Commit to an answer before you look.

const nested = [[1]];
const copy = [...nested];
copy[0].push(2);
console.log(nested[0]);
Output
[ 1, 2 ]

Check yourself

If you assign an array to a new variable (e.g., `let arr2 = arr1;`), what actually gets copied?

Reveal answer

The reference to the original array — Assigning an array to a new variable only copies the reference in memory, not the array itself.

What does the spread operator (`...`) do when used on an array?

Reveal answer

Expands the array's elements — The spread syntax expands iterables, like arrays, into their individual elements.

Can the spread operator be used multiple times within a single array literal?

Reveal answer

Yes, to merge multiple arrays and elements — You can use the spread operator multiple times, like `[...arr1, ...arr2]`, to merge several arrays.

Challenges

Challenge 1 +20 XP

Create a true copy of `sourceArray` and assign it to `newArray` using the spread operator.

javascript
  • Test 1 — expects "[ 'a', 'b', 'c' ]\n"
Need a hint? (−25% XP)

Put `...sourceArray` inside square brackets `[]`.

Show solution (0 XP)
const sourceArray = ['a', 'b', 'c'];
const newArray = [...sourceArray];
console.log(newArray);

Challenge 2 +20 XP

Merge `array1` and `array2` into a new array named `combined` using the spread operator.

javascript
  • Test 1 — expects "[ 1, 2, 3, 4 ]\n"
Need a hint? (−25% XP)

Use `[...array1, ...array2]`.

Show solution (0 XP)
const array1 = [1, 2];
const array2 = [3, 4];
const combined = [...array1, ...array2];
console.log(combined);

🐞 Bug Hunt +25 XP

A developer tried to make a backup copy of their `scores` array before modifying it, but the `backup` array also got modified! Fix the code so that the `backup` array remains a true, independent copy.

This code runs. It just does the wrong thing. Read it, find the defect, fix it — the tests below decide when you are right.

javascript
  • Test 1 — expects "3\n"
Need a hint? (−25% XP)

Assigning an array to a new variable just copies the reference. Use the spread operator inside an array literal `[...array]` to create a true, independent shallow copy.

Show solution (0 XP)
const scores = [10, 20, 30];
const backup = [...scores];

scores.push(40);
console.log(backup.length);