DevAcademy
LearnJavaScriptThe Spread Operator
BeginnerJavaScript

The Spread Operator

Learn how the spread operator (...) expands arrays, objects, and iterables in place — for copying, merging, passing arguments, and more — along with its shallow-copy caveat.

Reading Time

14 min

Lesson

Lesson 24 of 48

Introduction

The spread operator, written as three dots (...), takes an iterable — an array, a string, or an object with the spread syntax support — and expands it into its individual elements wherever it's used. It looks identical to the rest pattern you'll meet in the next lesson, but the two do opposite jobs: spread expands a collection into individual values, while rest gathers individual values back into a collection. Spread shows up constantly in modern JavaScript for copying, merging, and passing data around without mutating the original.

Spreading Arrays: Copying

Spreading an array into a new array literal creates a shallow copy — a brand-new array containing the same elements, but a completely different array in memory. This matters because arrays are reference types in JavaScript: assigning one array variable to another just copies the reference, so mutating one would affect the other. Spread avoids that by building an actual new array.

Copying Arrays Example

Try it yourself — edit and run

Console Output

Click “Run” to see the console output here.

Spreading Arrays: Merging

Because spread expands an array's elements in place, you can interleave multiple arrays — and even extra individual values — into a single new array literal. This replaces the older approach of using .concat() and reads more naturally, especially when combining more than two arrays or mixing in standalone values.

Merging Arrays Example

Try it yourself — edit and run

Console Output

Click “Run” to see the console output here.

Spreading Objects

Since ES2018, the same ... syntax works on objects too. Spreading an object into a new object literal copies its own enumerable properties into that new object, again producing a genuinely separate object rather than a shared reference. Just like with arrays, this is the standard modern way to copy and merge objects immutably.

Copying and Merging Objects Example

Try it yourself — edit and run

Console Output

Click “Run” to see the console output here.

Overriding Keys While Merging

When two spread objects share a property name, the one that appears later in the object literal wins — its value overwrites the earlier one. This makes spread a convenient way to apply overrides or updates on top of a base object: spread the defaults first, then spread the overrides after them so the overrides take priority.

Overriding Keys Example

Try it yourself — edit and run

Console Output

Click “Run” to see the console output here.

Spreading into Function Calls

Spread can also expand an array directly into a function call's argument list, passing each element as a separate positional argument. This replaces the old Function.prototype.apply() trick that was previously needed to call a function with an array of arguments, and it works with any function, including built-ins like Math.max() that don't natively accept an array.

Spreading into Function Calls Example

Try it yourself — edit and run

Console Output

Click “Run” to see the console output here.

Spreading Strings

Strings are iterable, so spreading a string expands it into an array of its individual characters. This is a quick way to turn a string into a character array without calling .split(""), and — unlike some legacy string-to-array tricks — it correctly handles multi-byte Unicode characters, such as emoji, as single elements.

Spreading Strings Example

Try it yourself — edit and run

Console Output

Click “Run” to see the console output here.

Common Spread Use Cases

Use CaseExample
Copy an array[...originalArray]
Merge arrays[...arrayA, ...arrayB]
Copy an object{ ...originalObject }
Merge/override objects{ ...defaults, ...overrides }
Pass array elements as argumentsfn(...argsArray)
Convert a string to characters[...someString]

Spread Works with Any Iterable

Spread isn't limited to arrays and objects — anything iterable works, including Sets and Maps. [...new Set([1, 1, 2, 2, 3])] is a common one-liner for deduplicating an array, since converting to a Set first removes duplicates and spreading converts it straight back into an array.

Spread Only Copies One Level Deep

Spread performs a shallow copy: it copies top-level values, but if a property or element is itself an object or array, only the reference to that nested structure is copied — not a fresh copy of its contents. Mutating a nested object inside the "copy" will also change it inside the original, because both point to the very same nested object in memory. For deeply nested data, you need a deep clone (such as structuredClone()) instead of spread.

Shallow Copy Caveat Example

Try it yourself — edit and run

Console Output

Click “Run” to see the console output here.

Interview Questions

Quick Quiz

1. What does [...[1, 2], ...[3, 4]] evaluate to?

2. In { ...defaults, ...overrides }, which object's value wins for a shared key?

3. What does [..."hi"] evaluate to?

4. Given const b = { ...a }; b.nested.value = 99;, what happens to a.nested.value if "nested" is an object?

5. What is the old, pre-spread way to call Math.max() with an array of numbers?