Copying objects and arrays is a core skill in JavaScript development, especially when dealing with immutable patterns, state management, and nested data structures. Here’s 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 | reliable | Extra dependency |
Rule of thumb: if the object is flat, spread it. If it has nesting and you mutate the clone, use structuredClone. Reach for Lodash only when you need circular reference support.