Deep vs. Shallow Copy in JavaScript: A Practical Guide
Copying objects and arrays is a core skill in JavaScript development, especially when dealing with immutable patterns, state management, and nested data structures. This guide explains the difference between shallow copy and deep copy, shows how to implement both, and provides practical examples and best‑use cases.
Read also: How to Clone Complex JavaScript Objects with structuredClone()
What Is the Difference?
Shallow Copy
A shallow copy duplicates only the top-level properties. Any nested objects remain references to the original.
- Fast and lightweight
- Not safe when modifying nested objects
Deep Copy
A deep copy fully duplicates the entire object structure recursively. Changing any nested values does not affect the original.
- Safe for immutable logic
- More resource‑intensive
Deep Copy Methods
1. JSON.stringify + JSON.parse
function deepClone(obj) {
return JSON.parse(JSON.stringify(obj));
}✔ Simple
✔ Good for plain objects
✘ Breaks on Date, Map, Set, RegExp, functions
✘ Fails on circular references
2. Recursive Deep Copy
function deepClone(obj) {
if (typeof obj !== 'object' || obj === null) return obj;
const clone = Array.isArray(obj) ? [] : {};
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
clone[key] = deepClone(obj[key]);
}
}
return clone;
}✔ Flexible
✔ Can support circular references with extra logic
✘ More code
✘ Requires manual handling of special types
3. structuredClone (Native Deep Copy)
const cloned = structuredClone(original);✔ Supports many built‑in types (Date, Map, Set, File, Blob)
✔ Fast and native
✘ Not available in old browsers
4. Lodash cloneDeep
import cloneDeep from 'lodash/cloneDeep';
const result = cloneDeep(data);✔ Battle‑tested
✔ Handles edge cases and circular structures
✘ Adds dependency
Shallow Copy Methods
1. Spread Operator
const copy = { ...original };
const arrCopy = [...originalArray];2. Object.assign
const copy = Object.assign({}, original);3. Array slice / concat
const copy = originalArray.slice();
const copy2 = originalArray.concat();4. Array.from
const copy = Array.from(originalArray);⚠ Nested objects remain linked to the original.
When to Use What?
Use Shallow Copy when:
- You only need top‑level cloning
- You work with flat data structures
- High performance is required
Use Deep Copy when:
- Modifying nested structures
- Using immutable patterns (React state, Redux, Zustand)
- Data integrity is critical
Key Considerations
Circular References
Deep-copy methods must detect them:
// JSON-based methods will fail:
// TypeError: Converting circular structure to JSONSpecial Object Types
For Date, RegExp, Map, Set, File, Blob → use structuredClone or Lodash.
Performance
Deep cloning large objects can be expensive. Benchmark before using in hot code paths.
Summary
| Method | Type | Pros | Cons |
|---|---|---|---|
| Spread | Shallow | Fast, simple | Shares nested refs |
| JSON clone | Deep | Simple | Breaks on many types |
| Recursion | Deep | Flexible | Complex, slower |
| structuredClone | Deep | Fast, native | Browser support varies |
| Lodash cloneDeep | Deep | Robust | Extra dependency |
Deep and shallow copying are essential for safe, predictable data handling in JavaScript. With these techniques, you can confidently manage complex state, avoid mutation bugs, and write cleaner, more maintainable code.