Q&A
Deep copying vs. shallow copying
Overview
Copying an object seems simple until you realize objects can contain other objects. Shallow copy gives you a new container with the same nested references; deep copy gives you a completely independent tree. The right choice depends on whether you want changes to nested data to propagate or be isolated.
graph TD
A[Original: {name, address:{city,zip}}] --> B[Shallow copy]
A --> C[Deep copy]
B --> D["New top-level object<br/>but address IS THE SAME OBJECT"]
C --> E["Entirely new object<br/>address is a NEW object too"]
D --> F["Mutate copy.address.city → changes original too!"]
E --> G["Mutate copy.address.city → original unchanged ✓"]
style E fill:#1e1b4b,color:#fff
The Core Difference Illustrated
Python
import copy
original = {"name": "Ada", "scores": [90, 85, 78]}
# Shallow copy
shallow = original.copy() # or dict(original) or {**original}
shallow["name"] = "Linus" # OK - doesn't affect original
shallow["scores"].append(100) # ⚠ ALSO modifies original["scores"]!
print(original["scores"]) # [90, 85, 78, 100] - unexpected!
# Deep copy
deep = copy.deepcopy(original)
deep["scores"].append(999)
print(original["scores"]) # [90, 85, 78, 100] - untouched ✓
JavaScript
const original = { name: "Ada", address: { city: "London" } };
// Shallow copy (Object.assign or spread)
const shallow = { ...original };
shallow.name = "Linus"; // primitive - doesn't affect original
shallow.address.city = "Paris"; // ⚠ same nested object - original also changed!
// Deep copy (structuredClone - modern, built-in)
const deep = structuredClone(original);
deep.address.city = "Berlin"; // original.address.city stays "Paris"
Java
// Shallow: clone() (default Object.clone() copies top-level fields)
// Deep: implement Cloneable + clone all nested, or use serialization,
// or copy constructors, or libraries (Jackson, Kryo).
Shallow Copy Methods by Language
| Language | Shallow copy |
|---|---|
| Python | obj.copy(), list[:], dict(d), {**d}, copy.copy() |
| JavaScript | {...obj}, Object.assign({}, obj), [...arr] |
| Java | Object.clone() (default), copy constructors |
| C++ | Copy constructor (default memberwise = shallow) |
Deep Copy Methods by Language
| Language | Deep copy |
|---|---|
| Python | copy.deepcopy(obj) |
| JavaScript | structuredClone(obj) (modern), JSON.parse(JSON.stringify(obj)) (limited) |
| Java | Implement Cloneable recursively, or serialization, or libraries |
| C++ | Override copy constructor to deep-copy pointers |
JavaScript: JSON round-trip limitations
JSON.parse(JSON.stringify(obj))
// Loses: undefined, functions, Date (becomes string), Map/Set, circular refs
// Use structuredClone() instead for real deep copies
When to Use Which
- Shallow copy - when nested objects are immutable (strings, numbers, frozen objects) or when you intentionally want shared references (e.g. copying a list of references to the same objects).
- Deep copy - when the copy must be completely independent, especially when you'll mutate nested data. Costs more memory and time proportional to the object graph's depth.
Why This Matters in Interviews
This is one of the highest-frequency conceptual questions across all languages. The signal: clearly explain that shallow copy shares nested references (so mutations to nested data affect both), while deep copy creates a fully independent clone. Giving a concrete broken-shallow-copy example, showing the fix (language-appropriate deep copy), and naming the trade-offs (deep copy costs O(n) vs shallow O(1)) shows mastery. Every language has language-specific gotchas - mention them for whatever stack the role uses.
Common Pitfalls
- Assuming
{...obj}orlist.copy()is a deep copy - it's shallow. JSON.parse(JSON.stringify(...))losingDate,undefined,Map,Set, functions, and circular refs.- Forgetting that even "deep copy" libraries may not copy functions, class methods, or prototypes.
- In Java,
Object.clone()is shallow by default - you must manually deep-clone each field. - Mutating a shallow copy's nested data and being surprised the original changed.
References
- Python
copymodule: https://docs.python.org/3/library/copy.html - MDN
structuredClone: https://developer.mozilla.org/en-US/docs/Web/API/structuredClone