JavaScript Spread Operator
Table of Contents + β
In the previous lesson, we learned how to pull values out of arrays and objects into variables. Now letβs go the other way and learn the spread operator, which spreads the items of an array or the properties of an object into a new one.
π¦ What is the Spread Operator?
The spread operator is three dots ... placed in front of an array or object. It takes the items inside and lays them out individually into a new array or object. Think of it as unpacking a box and placing each item into a fresh box.
const numbers = [1, 2, 3];const copy = [...numbers];
console.log(copy); // [1, 2, 3]Letβs walk through what each line does:
const numbers = [1, 2, 3]makes our starting array.[...numbers]spreads the three items out, one by one, into a fresh pair of square brackets.const copystores that fresh array, which holds the same values1,2, and3.
So ...numbers unpacks the items, and the new array is a separate box that happens to hold the same things.
π Copying an Array
To copy an array, spread it into a new pair of square brackets. This gives you a separate array, so changing the copy does not touch the original.
const original = ["a", "b", "c"];const copy = [...original];
copy.push("d");
console.log(copy); // ["a", "b", "c", "d"]console.log(original); // ["a", "b", "c"] β unchangedLetβs trace it line by line:
[...original]spreads the three letters into a brand new array stored incopy.copy.push("d")adds"d"to the copy only.- The first
console.logshows the copy now has four items. - The second
console.logshowsoriginalstill has three, because the copy and the original are two different arrays.
π Combining Arrays
You can spread more than one array into the same new array to join them together. The items come out in the order you write them.
const fruits = ["apple", "banana"];const veggies = ["carrot", "pea"];
const food = [...fruits, ...veggies];
console.log(food); // ["apple", "banana", "carrot", "pea"]Here is what happens step by step:
...fruitsspreads"apple"and"banana"into the new array first....veggiesthen spreads"carrot"and"pea"right after them.- Because
fruitsis written beforeveggies, its items land first, giving us one combined array in that order.
You can also drop extra values in between the spreads to add items while combining.
const more = [...fruits, "cherry", ...veggies];
console.log(more); // ["apple", "banana", "cherry", "carrot", "pea"]This shows that spreads and plain values can sit side by side:
...fruitsspreads in"apple"and"banana"."cherry"is a single value dropped in at that exact spot....veggiesspreads in"carrot"and"pea"after it.
Each part is placed in the order you write it, so "cherry" ends up in the middle.
π§± Copying and Merging Objects
The spread operator works on objects too. It copies the properties of one object into a new one, and you can add new properties at the same time.
const user = { name: "Alex", age: 30 };const updated = { ...user, age: 31 };
console.log(updated); // { name: "Alex", age: 31 }console.log(user); // { name: "Alex", age: 30 } β unchangedLetβs break down the new object:
...usercopies every property fromuser, so we start withname: "Alex"andage: 30.age: 31comes after the spread, so it overrides the copiedage.updatedends up with the new age, whileuserkeeps its originalage: 30untouched.
You can merge two objects the same way. When both objects have the same property, the one written later wins.
const defaults = { theme: "light", fontSize: 14 };const settings = { fontSize: 16 };
const final = { ...defaults, ...settings };
console.log(final); // { theme: "light", fontSize: 16 }Here is how the merge plays out:
...defaultscopies intheme: "light"andfontSize: 14first....settingscopies infontSize: 16next.- Both objects have
fontSize, and sincesettingsis spread last, its16overwrites the14. themeonly exists indefaults, so it carries through unchanged.
π‘οΈ Updating Without Mutating
The spread operator creates a shallow copy, which means you get a new array or object instead of changing the one you already have. This is handy when you want to add an item or update a property while keeping the original untouched.
// β
Add an item to an array without changing the originalconst cart = ["shoes", "hat"];const newCart = [...cart, "socks"];
console.log(newCart); // ["shoes", "hat", "socks"]console.log(cart); // ["shoes", "hat"] β still the sameLetβs see how the original stays safe:
...cartspreads"shoes"and"hat"into a new array."socks"is added at the end of that new array.newCarthas all three items, whilecartis never touched and still holds two.
// β
Update one property of an object without changing the originalconst profile = { name: "Sam", role: "guest" };const upgraded = { ...profile, role: "admin" };
console.log(upgraded); // { name: "Sam", role: "admin" }console.log(profile); // { name: "Sam", role: "guest" } β still the sameThe same idea works for objects:
...profilecopiesname: "Sam"androle: "guest"into a new object.role: "admin"comes after the spread, so it overrides the copiedrole.upgradedshows the new role, whileprofilekeepsrole: "guest".
Very common in React
React expects you to create new arrays and objects instead of editing the old ones. The spread operator is the standard way to update state immutably, so you will use it constantly when building React apps.
πͺ Shallow Copy, Not Deep Copy
A shallow copy copies the top level only. If a value inside is itself an array or object, the copy and the original still share that same inner value.
const team = { name: "Blue", members: ["Alex", "Sam"] };const clone = { ...team };
clone.members.push("Jordan");
console.log(team.members); // ["Alex", "Sam", "Jordan"] β also changed!Letβs see why the original changed too:
{ ...team }copies the top-level properties, sonameis copied as a value butmembersis copied as a reference to the same array.clone.members.push("Jordan")reaches into that shared array and adds"Jordan".- Because both objects point at the same
membersarray, the new name shows up inteam.membersas well.
When you need a deep copy
For a fully independent copy, including nested arrays and objects, use
structuredClone(value). The spread operator only protects the top level.
β οΈ Common Mistakes to Avoid
| Mistake | Problem | Solution |
| Confusing spread with rest | Both use ..., but rest collects values into an array | Spread unpacks values out; rest gathers them in |
| Expecting a deep copy | Nested arrays and objects are still shared | Use structuredClone(...) for nested data |
| Wrong order when overriding | { age: 31, ...user } puts the old age back | Spread first, then list the property you want to override |
π§ Try It Yourself!
- Make an array of three numbers and create a copy with
[...arr], then add a number to the copy and confirm the original is unchanged. - Combine two arrays into one using two spreads.
- Create an object with a couple of properties, then make a new object that copies it but overrides one property.
- Merge two objects that share a property and check which value wins based on order.
π§© What Youβve Learned
- β
The spread operator
...unpacks the items of an array or the properties of an object into a new one - β
[...arr]copies an array, and[...a, ...b]combines arrays - β
{ ...obj, newProp: 1 }copies an object and can add or override properties - β When merging objects, the property written last wins
- β Spread makes a shallow copy, so the original stays untouched but nested values are still shared
π Whatβs Next?
The spread operator unpacks values out, but the same ... symbol can also gather values together. Letβs continue to Rest Parameters.