Assigning an object to another variable does not copy it. Both names point to the same object.
const a = { name: "Maya", scores: [1, 2] };
const b = a;
b.name = "Changed";
console.log(a.name); // → Changed
To make an actual copy, you have two levels to choose from.
Shallow copy
A shallow copy duplicates the top level. Nested objects and arrays are still shared.
const original = { name: "Maya", scores: [1, 2] };
const copy = { ...original }; // or Object.assign({}, original)
copy.name = "Meera";
copy.scores.push(3);
console.log(original.name); // → Maya (separate)
console.log(original.scores); // → [1, 2, 3] (shared!)
Shallow copies are quick and fine when the object has only primitive values, or when you replace nested parts rather than change them.
Deep copy: structuredClone
structuredClone() makes an independent copy of nested data. It is built into modern browsers and Node.js.
const original = { name: "Maya", scores: [1, 2], when: new Date(0) };
const deep = structuredClone(original);
deep.scores.push(3);
console.log(original.scores); // → [1, 2]
console.log(deep.scores); // → [1, 2, 3]
console.log(deep.when instanceof Date); // → true
It copies Dates, Maps, Sets, arrays and plain objects, and handles circular references. It cannot copy functions, DOM nodes or class instances’ methods (it throws a DataCloneError for functions).
The old trick: JSON
const copy = JSON.parse(JSON.stringify({ a: 1, b: [2, 3] }));
console.log(copy); // → { a: 1, b: [2, 3] }
It works for simple data, but it breaks other things: Dates become strings, undefined and functions disappear, NaN becomes null, Maps and Sets become empty objects. Prefer structuredClone().
Which should I use?
| Situation | Use |
|---|---|
| Copy flat data, or replace nested parts | spread { ...obj } |
| Independent copy of nested data | structuredClone(obj) |
| Immutable updates of nested state | spread at every level you change |
const state = { user: { name: "Maya", age: 28 }, items: [1, 2] };
// change only user.age, keep everything else
const next = { ...state, user: { ...state.user, age: 29 } };
console.log(state.user.age, next.user.age); // → 28 29
console.log(state.items === next.items); // → true (reused, not copied)
Arrays are objects too
[...arr] is shallow, and structuredClone(arr) is deep.