What you'll be able to do
By the end of this page you should be able to build a new object with the spread operator ..., override fields cleanly, pull leftover fields with rest, and explain why nested objects inside a spread copy are still shared.
Previous post: destructuring objects and arrays.
Who this is for
- People who write
Object.assign({}, user)and want the{ ...user }form - Beginners who think spread is a deep clone
- Anyone updating one field without mutating the original (a habit that pays off later in UI state)
You can skip this if shallow vs nested sharing already feels clear. Come back when a “copy” still changes the nested address on the original.
Spread: copy own enumerable fields into a new object
const user = { name: "Asha", role: "editor" };
const copy = { ...user };
copy.role = "admin";
console.log(user.role); // "editor"
console.log(copy.role); // "admin"
Scenario A — change one field for a new version. Keep the previous object intact.
Scenario B — merge defaults with overrides. Later keys win:
const base = { theme: "light", compact: false };
const next = { ...base, theme: "dark" };
Rest: gather the leftover fields
In destructuring, ... on the left gathers what you did not name.
const post = { id: 1, title: "Spread", draft: true };
const { draft, ...publicFields } = post;
console.log(publicFields); // { id: 1, title: "Spread" }
Scenario A — omit a secret or draft flag before logging.
Scenario B — pass “everything else” to a child. Rest makes a new object of leftovers (still shallow).
Shallow copy myth (important)
const original = { name: "Asha", address: { city: "Pune" } };
const copy = { ...original };
copy.address.city = "Delhi";
console.log(original.address.city); // "Delhi" — nested object was shared
Scenario A — flat user with only strings/numbers. Spread copy is usually enough.
Scenario B — nested address or meta. Spread copies the top level; nested objects stay shared references. Deep copy comes later (structuredClone / careful recipes). For now: know the limit.
Arrays still use spread too
You already met [...list] for arrays. Same idea: new outer list, shared nested objects if any.
Scenario A — add an item without push on the original. const next = [...list, item].
Scenario B — object vs array. { ...obj } for objects; [...arr] for arrays — do not mix the brackets.
A tiny practice file
Save as spread-rest.html.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>spread rest</title>
</head>
<body>
<button id="flat">Flat copy</button>
<button id="nested">Nested surprise</button>
<pre id="out"></pre>
<script>
const out = document.getElementById("out");
document.getElementById("flat").addEventListener("click", function () {
const user = { name: "Asha", role: "editor" };
const copy = { ...user, role: "admin" };
out.textContent =
"original role: " + user.role + "\n" +
"copy role: " + copy.role;
});
document.getElementById("nested").addEventListener("click", function () {
const original = { name: "Asha", address: { city: "Pune" } };
const copy = { ...original };
copy.address.city = "Delhi";
out.textContent =
"original city: " + original.address.city + "\n" +
"(nested object was shared)";
});
</script>
</body>
</html>
Mistakes I see a lot
1. Believing spread deep-clones. Nested objects stay shared.
2. Spreading null or undefined into an object. Prefer { ...(user ?? {}) }.
3. Mutating the original after a “copy” that was actually assignment. const copy = user is not spread.
4. Rest without understanding omit. Named fields are pulled out; rest is the leftover object.
5. Overusing deep clone. Most UI updates need a new top-level object and careful nested updates — not a full deep clone every time.
6. Mixing array and object spread syntax. Brackets matter.
What to try before the next post
{ ...user, role: "admin" }and prove the original role is unchanged.- Omit one field with rest.
- Reproduce the nested
addresssurprise once. - Build the tiny HTML file.
Next in this series: primitives vs references — the mental model behind user2 = user1 and why numbers do not behave the same way.
Try this next outside the series
Objects and references click faster when you connect them to state, payloads, and database-shaped data.
- MERN MongoDB modeling — see objects turn into real documents and nested structures
- JSON Formatter — inspect deep objects before you mutate or copy them