Q118: Structured Clone, JSON Serialization and Deep Copy
What Interviewers Want To Evaluate
This question checks whether you understand copying and serialization trade-offs. Interviewers want shallow copy, deep copy, structuredClone, JSON limitations, transferable objects, circular references, prototypes, functions, dates, maps, sets, and immutable update patterns.
Senior answers should know when copying is the wrong abstraction.
Short Interview Answer
A shallow copy copies only the top-level container. Nested objects are still shared. A deep copy duplicates nested data. JSON.stringify and JSON.parse can create a limited deep copy for JSON-safe data, but they lose types such as Date, Map, Set, undefined, functions, symbols, and circular references. structuredClone supports many richer built-in types and circular references, but it still does not clone functions or preserve all custom class behavior. For application state, targeted immutable updates are often better than deep cloning everything.
Detailed Interview Answer
Copying is easy to say and easy to get subtly wrong.
const original = {
user: {
name: "Asha",
},
};
const copy = { ...original };
copy.user.name = "Meera";
console.log(original.user.name); // "Meera"
The top-level object was copied. The nested user object was shared.
Shallow Copy
Shallow copy methods include:
object spread
Object.assign
array spread
Array.prototype.slice
Array.from
These are useful when nested values can be shared or when you update nested structures deliberately.
Deep Copy
A deep copy recursively copies nested data.
Deep copy is useful when the new structure must be independent from the original structure.
But deep copy can be expensive and can hide unclear ownership.
JSON Copy
The classic JSON trick is:
const copy = JSON.parse(JSON.stringify(value));
This works only for JSON-safe data.
It loses or changes many JavaScript values.
JSON Limitations
JSON serialization does not preserve:
undefined
functions
symbols
Date objects as Date instances
Map and Set
RegExp
BigInt
circular references
custom prototypes
non-enumerable properties
property descriptors
Dates become strings. undefined may disappear. Circular references throw.
structuredClone
structuredClone is a modern deep-copy API.
const copy = structuredClone({
createdAt: new Date(),
tags: new Set(["js", "browser"]),
});
It supports many built-in types better than JSON.
Circular References
structuredClone supports circular references.
const item = { name: "node" };
item.self = item;
const copy = structuredClone(item);
console.log(copy.self === copy); // true
JSON serialization would throw on this structure.
Transferable Objects
Some objects can be transferred instead of copied, such as ArrayBuffer.
const buffer = new ArrayBuffer(1024);
const clone = structuredClone(buffer, {
transfer: [buffer],
});
Transfer can improve performance because ownership moves instead of duplicating memory.
This is common in worker-heavy code.
Functions and Class Instances
structuredClone does not clone functions.
Custom class instances may not preserve behavior the way people expect.
If behavior matters, copying raw data is usually clearer than cloning live objects.
Immutable State Updates
In React and similar systems, you usually do not deep clone entire state trees.
You copy the path that changed.
const nextState = {
...state,
user: {
...state.user,
name: "Meera",
},
};
This preserves structural sharing and is efficient for change detection.
Copying vs Normalizing
Large nested structures are often better normalized.
const state = {
usersById: {
u1: { id: "u1", name: "Asha" },
},
selectedUserId: "u1",
};
Updating one entity becomes a targeted copy instead of a deep tree clone.
Common Mistakes
A common mistake is using JSON copy for data containing dates and then wondering why date methods fail.
Another mistake is deep cloning state on every update, causing unnecessary CPU and memory usage.
Another mistake is assuming object spread clones nested data.
Senior Trade-Offs
Copying should match ownership. If a function owns data and must isolate mutations, copying helps. If the data is large and shared by design, deep copying can be wasteful.
Prefer immutable targeted updates, normalized data, or explicit serialization boundaries.
Code or Design Example
function updateTodoTitle(state, todoId, title) {
return {
...state,
todosById: {
...state.todosById,
[todoId]: {
...state.todosById[todoId],
title,
},
},
};
}
Only the changed path is copied.
Debugging Workflow
When copying behaves incorrectly:
check shallow vs deep copy expectation
check nested object sharing
check JSON-unsafe values
check circular references
check Date, Map, Set, BigInt, functions, symbols
check class instance behavior
measure large clone cost
consider targeted immutable updates
Interview Framing
Start with shallow copy vs deep copy. Then compare JSON copy and structuredClone, and close with why state updates usually copy only changed paths.
Revision Notes
Object spread is shallow. JSON copy is limited. structuredClone is richer but not universal. Deep cloning is not always the best design.
Key Takeaways
Copying is a data ownership decision. Use the smallest copy that preserves correctness and keeps performance reasonable.
Follow-Up Questions
- What is a shallow copy?
- What is a deep copy?
- Why does object spread share nested objects?
- What does JSON copy lose?
- What does
structuredClonesupport better than JSON? - Can
structuredClonecopy functions? - What are transferable objects?
- Why can deep cloning state be expensive?
- What is structural sharing?
- When should data be normalized?
How I Would Answer This In A Real Interview
I would explain shallow copy first, then show why nested references remain shared. Then I would compare JSON copy with structuredClone, mention unsupported values, and close by saying frontend state usually needs targeted immutable updates instead of full deep clones.