Volume 2

Q118: Structured Clone, JSON Serialization and Deep Copy

Difficulty: SeniorFrequency: MediumAnswer time: 8-12 minutes

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

  1. What is a shallow copy?
  2. What is a deep copy?
  3. Why does object spread share nested objects?
  4. What does JSON copy lose?
  5. What does structuredClone support better than JSON?
  6. Can structuredClone copy functions?
  7. What are transferable objects?
  8. Why can deep cloning state be expensive?
  9. What is structural sharing?
  10. 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.