How do you clone an object or array in JavaScript?

Beginner10 min interview
Skills tested:
Shallow vs deep copy distinctionReference type behavior in JavaScriptstructuredClone and JSON deep copy limitationsImmutability patterns in state managementChoosing the right cloning strategy for the data shape

Advertisement

🧩 Scenario

In a real codebase, you will encounter this when managing state in React, building undo/redo systems, writing pure functions, or working with any data pipeline where the original value must remain unchanged. Accidentally mutating a reference-type value is one of the most common bugs in JavaScript, and it often produces errors that are difficult to trace because the original data appears to have changed without any obvious assignment. Knowing exactly what each cloning method copies and what it leaves as a shared reference is a practical daily skill.

Architecture Walkthrough

How JavaScript Stores Reference Types

Primitive values like numbers, strings, and booleans are stored directly in memory. When you assign a primitive to a new variable, you get an independent copy. Objects and arrays are stored as references: the variable holds a pointer to a location in memory, not the actual data. When you assign an object to another variable without cloning, both variables point to the same memory location. Changing one changes the other.

This is why cloning is necessary whenever you want to produce an independent copy of an object or array. Without an explicit clone, any modification to the "copy" will silently affect the original.

Shallow Copies: Spread, Object.assign, and Array.from

Shallow copying creates a new top-level object or array, but any nested values that are reference types still share the same memory address as the original. The spread operator ({...obj} or [...arr]), Object.assign({}, obj), and Array.from(arr) all produce shallow copies.

For flat structures (objects or arrays that contain only primitives), a shallow copy is sufficient and is the most performant option. The problem arises when your data contains nested objects or arrays. Modifying a nested property in the copy will modify it in the original as well, because both point to the same nested object in memory.

Deep Copies: JSON, structuredClone, and Libraries

A deep copy recursively copies every value, including nested objects and arrays, so that no part of the clone shares a reference with the original. The oldest approach is JSON.parse(JSON.stringify(obj)), which serializes the object to a JSON string and then parses it back. This works well for simple plain objects and arrays containing only JSON-compatible types.

The JSON approach silently drops undefined values, converts Date objects to strings, loses functions entirely, and throws on circular references. The modern native alternative is structuredClone(obj), available in Node.js 17+ and all modern browsers. It handles Date, Map, Set, ArrayBuffer, and circular references correctly, making it the preferred choice for deep cloning in most production scenarios. For very complex cases, libraries like Lodash provide cloneDeep.


Key Code Explained

const original = {
  name: 'Ghazi',
  skills: ['React', 'Node'],
  address: { city: 'Lahore' },
};

// Shallow copy: top-level properties are independent
const shallow = { ...original };
shallow.name = 'Ali'; // original.name is still 'Ghazi'
shallow.address.city = 'Karachi'; // original.address.city is now 'Karachi' too

// Deep copy with structuredClone: fully independent
const deep = structuredClone(original);
deep.address.city = 'Karachi'; // original.address.city remains 'Lahore'

// JSON approach: works for plain data, but loses non-JSON types
const jsonClone = JSON.parse(JSON.stringify(original));

// JSON approach failure cases
const tricky = {
  date: new Date(), // becomes a string in the clone
  fn: () => 'hello', // silently dropped
  value: undefined, // silently dropped
};
const brokenClone = JSON.parse(JSON.stringify(tricky));
// brokenClone.date is a string, brokenClone.fn is undefined, brokenClone.value is undefined

The shallow copy example shows exactly where the reference sharing happens: top-level primitive properties are independent, but nested objects are shared. This is the most common source of confusion and bugs when cloning in JavaScript.


Tradeoffs

ApproachProCon
Spread / Object.assignFast, zero dependencies, sufficient for flat dataNested references are shared, not truly independent
JSON.parse/JSON.stringifyWorks without any library, familiar patternDrops functions and undefined, mangles Dates, fails on circular refs
structuredCloneNative, handles Dates, Sets, Maps, circular refsNot available in older environments, cannot clone functions
Lodash cloneDeepHandles virtually all casesAdds a dependency, slower for large objects

What Interviewers Actually Check

  • Whether you can distinguish a shallow copy from a deep copy using a concrete nested example
  • Whether you know the limitations of the JSON round-trip approach and can name specific failure cases
  • Whether you know structuredClone exists and when to use it over JSON
  • Whether you understand why immutability matters in state management contexts like React
  • Whether you can correctly predict the behavior of spread on a nested object
  • Whether you reach for the simplest tool (shallow copy) when the data is flat, rather than always deep cloning

Follow-Up Questions

  1. How does React detect state changes, and why does mutating a cloned object that still shares nested references cause bugs in a React component?
  2. What would happen if you called structuredClone on an object containing a function or a class instance?
  3. How would you write a test to verify that a cloning utility produces a truly independent deep copy?
  4. If you need to clone a very large nested object hundreds of times per second for a real-time feature, what performance concerns would you raise?
  5. A PR you are reviewing uses JSON.parse(JSON.stringify(data)) to clone API response data. What questions would you ask before approving it?

Common Candidate Mistakes

  • Using spread or Object.assign and assuming nested objects are fully cloned when they are only shallow copied
  • Using JSON.parse(JSON.stringify()) on data that contains functions, undefined, Date objects, or circular references, without knowing what gets dropped or mutated
  • Modifying a cloned array element that is itself an object, and being surprised that the original was changed
  • Not knowing that structuredClone exists as a built-in native alternative to the JSON approach
  • Treating Array.from or slice as deep clones when they produce shallow copies exactly like spread

Interview Readiness Checklist

Before you leave this question, make sure you can answer:

  • Can you explain the difference between a shallow copy and a deep copy with a concrete nested object example?
  • Can you list at least three methods for creating a shallow copy of an object or array?
  • Can you explain why JSON.parse/JSON.stringify fails with functions, Date objects, and circular references?
  • Can you describe when structuredClone is preferable to the JSON approach?
  • Can you explain why immutability matters when managing state in React or Redux?
  • Can you identify which cloning strategy to reach for given a specific data shape?

Summary

Cloning in JavaScript requires understanding how reference types are stored. Primitives copy by value, while objects and arrays copy by reference. Without an explicit clone, two variables pointing to the same object will both reflect any modification made through either one.

For flat data, a shallow copy using spread or Object.assign is sufficient and performant. For nested data, you need a deep clone. The modern native choice is structuredClone, which handles Date, Map, Set, and circular references correctly. The older JSON approach works for simple plain objects but silently drops or transforms several data types, making it a footgun in production codebases.

The most important interview signal on this question is not knowing every method by name, but understanding the trade-off between shallow and deep copies and being able to predict what breaks when the wrong approach is used on nested data.

Related Videos
Watch these videos to learn more about this topic
Frequently Asked Questions

Does spread operator create a deep copy?

No, it only creates a shallow copy — nested objects still reference the original.

Advertisement


Stay Updated

Get the latest frontend challenges, interview questions and tutorials delivered to your inbox.

Advertisement