JavaScript: Shallow Copy vs Deep Copy
In JavaScript, objects and arrays are Reference Types. When you assign an object to a new variable, you aren't copying the data; you're just copying a memory pointer. If you mutate the copy, the original changes too.
To safely duplicate an object without mutating the original, you must make a copy. However, not all copies are created equal.
1. Shallow Copy (The Surface-Level Clone)
A shallow copy creates a new object, but it only duplicates the first-level properties. If the original object contains nested objects or arrays, the shallow copy will simply duplicate the references to those nested structures.
Methods for Shallow Copying
- The Spread Operator (
...) Object.assign()- Array methods like
slice()orconcat()
The Shallow Copy Pitfall
const original = {
name: "Alice",
details: { age: 25 } // Nested object!
};
// Create a shallow copy
const shallowCopy = { ...original };
// Mutating a first-level property is safe
shallowCopy.name = "Bob";
console.log(original.name); // "Alice" (Original is unharmed)
// Mutating a nested property affects the original!
shallowCopy.details.age = 99;
console.log(original.details.age); // 99 (Original is mutated!)2. Deep Copy (The Complete Clone)
A deep copy clones every level of an object recursively. The new object is entirely independent of the original. Mutating the deep copy will never affect the original data.
Method 1: The Legacy Approach (JSON.parse / JSON.stringify)
For years, the standard hack for deep copying was converting the object to a JSON string and immediately parsing it back into a new object.
const original = { name: "Alice", details: { age: 25 } };
const deepCopy = JSON.parse(JSON.stringify(original));
deepCopy.details.age = 99;
console.log(original.details.age); // 25 (Original is unharmed!)The Flaw: JSON stringification strips out functions, undefined, Symbols, and throws errors on circular references or advanced object types (like Dates or Maps).
Method 2: The Modern Standard (structuredClone)
Introduced natively to browsers and Node.js in 2022, structuredClone is the official, performant way to deep-copy objects.
const original = {
name: "Alice",
birthday: new Date(),
details: { age: 25 }
};
// Creates a perfect deep clone, preserving Date objects!
const perfectClone = structuredClone(original);structuredClone elegantly handles cyclic graphs, Dates, Sets, Maps, and TypedArrays, making the JSON hack obsolete.
Summary Table
| Feature | Shallow Copy | Deep Copy (structuredClone) | JSON Deep Copy |
|---|---|---|---|
| Duplicates 1st-level primitives? | ✅ Yes | ✅ Yes | ✅ Yes |
| Duplicates nested objects? | ❌ No (Copies references) | ✅ Yes (Recursive clone) | ✅ Yes |
Preserves Date, Set, Map? | ✅ Yes (References) | ✅ Yes | ❌ No (Converts to strings or drops) |
| Preserves Functions? | ✅ Yes (References) | ❌ No (Throws Error) | ❌ No (Strips them) |
Senior-Level Interview Answer
In JavaScript, a shallow copy creates a new top-level object but merely copies memory references for any nested objects or arrays. Consequently, mutating deep properties within a shallow copy—such as those created via the spread operator or
Object.assign()—will unintentionally mutate the original object. A deep copy, conversely, recursively clones the entire object graph, ensuring absolute referential independence. Historically, developers relied on theJSON.parse(JSON.stringify())hack for deep copies, which fails on complex types like Dates, Sets, and functions. The modern, native solution isstructuredClone(), which utilizes the structured clone algorithm to perfectly deep-copy complex nested structures and handle circular references natively.
Common Interview Mistakes
❌ Thinking the Spread Operator is a Deep Copy
The most common mistake candidates make is assuming const copy = {...obj} completely detaches the objects. It only works if the object is perfectly flat (1D).
❌ Using structuredClone on DOM elements or Functions
While structuredClone is immensely powerful, the underlying algorithm intentionally cannot clone DOM nodes, Functions, or certain Error objects. If you attempt to pass an object containing a function to structuredClone, it will throw a DataCloneError.
