Skip to content

JavaScript Tutorial Objects

Copying Objects in JavaScript: Shallow vs Deep

Lesson 86 of 258 2 min read By Deepak Paswan Updated Oct 4, 2026

Assigning an object to another variable does not copy it. Both names point to the same object.

script.js
JS
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.

script.js
JS
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.

script.js
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

script.js
JS
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?

SituationUse
Copy flat data, or replace nested partsspread { ...obj }
Independent copy of nested datastructuredClone(obj)
Immutable updates of nested statespread at every level you change
script.js
JS
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)
info
Arrays are objects too
The same applies to arrays: [...arr] is shallow, and structuredClone(arr) is deep.