Shallow copy vs deep copy in JavaScript
Shallow vs Deep Copy
When copying objects in JavaScript, understanding the difference between shallow and deep copy is critical to avoid unexpected bugs.
The Problem
const original = { name: "Alice", scores: [90, 85, 92] };
const copy = original; // β Not a copy β just another reference!
copy.name = "Bob";
console.log(original.name); // "Bob" β original is also changed!Shallow Copy
A shallow copy creates a new object with copies of the top-level properties. However, nested objects are still shared (same references).
Methods for Shallow Copy
const obj = { a: 1, nested: { b: 2 } };
// Spread operator
const copy1 = { ...obj };
// Object.assign
const copy2 = Object.assign({}, obj);
// Array methods
const arr = [1, [2, 3]];
const arrCopy1 = [...arr];
const arrCopy2 = arr.slice();
const arrCopy3 = Array.from(arr);Shallow Copy Limitation
const original = { name: "Alice", address: { city: "Kyiv" } };
const shallow = { ...original };
shallow.name = "Bob"; // β
Independent
shallow.address.city = "Lviv"; // β Modifies original!
console.log(original.address.city); // "Lviv"Deep Copy
A deep copy creates a completely independent clone β all nested objects are also copied.
1. structuredClone() (Modern, Recommended)
const original = {
name: "Alice",
scores: [90, 85],
address: { city: "Kyiv" },
date: new Date()
};
const deep = structuredClone(original);
deep.address.city = "Lviv";
console.log(original.address.city); // "Kyiv" β
Independent!Supports: objects, arrays, Date, Map, Set, RegExp, ArrayBuffer, etc. Doesn't support: functions, DOM nodes, Error objects, symbols as keys.
2. JSON.parse(JSON.stringify())
const deep = JSON.parse(JSON.stringify(original));Limitations:
- β Loses
undefined, functions,Symbol - β Converts
Dateto string - β Doesn't handle circular references
- β Loses
Map,Set,RegExp
3. Custom Recursive Function
function deepClone(obj) {
if (obj === null || typeof obj !== "object") return obj;
if (obj instanceof Date) return new Date(obj);
if (obj instanceof RegExp) return new RegExp(obj);
if (Array.isArray(obj)) return obj.map(deepClone);
const clone = {};
for (const key of Object.keys(obj)) {
clone[key] = deepClone(obj[key]);
}
return clone;
}4. Libraries
// Lodash
import { cloneDeep } from 'lodash';
const deep = cloneDeep(original);Comparison Table
| Method | Type | Functions | Date | Circular |
|---|---|---|---|---|
{ ...obj } | Shallow | β | β | N/A |
Object.assign() | Shallow | β | β | N/A |
structuredClone() | Deep | β | β | β |
JSON.parse/stringify | Deep | β | β | β |
lodash.cloneDeep() | Deep | β | β | β |
Important:
Use structuredClone() for deep copying in modern environments (available in all browsers since 2022 and Node.js 17+). Use spread ({ ...obj }) for shallow copies. Avoid JSON serialization for complex objects with Dates, functions, or circular references.
Short Answer
Interview readyA concise answer to help you respond confidently on this topic during an interview.