Skip to content
⚠️ This article was written in 2019. Some content may be outdated.

Comparing JavaScript Deep Clone Approaches

Deep cloning is a topic that comes up constantly in JavaScript interviews and projects. There are many ways to do it — each with its own trade-offs.

Shallow Clone vs Deep Clone

javascript
// Shallow clone: first-level copy, nested objects still share references
const obj = { a: 1, b: { c: 2 } };
const shallow = { ...obj }; // or Object.assign({}, obj)
shallow.b.c = 99;
console.log(obj.b.c); // 99 — original is affected!

// Deep clone: completely independent copy, no shared references

Approach 1: JSON.parse(JSON.stringify(...))

javascript
const deep = JSON.parse(JSON.stringify(obj));

// ✅ Pros: one-liner, fast for most cases
// ❌ Cons:
//   - Loses undefined, Function, Symbol properties
//   - Date becomes a string
//   - Cannot handle circular references (throws)
//   - Loses RegExp, Map, Set

Approach 2: structuredClone (Modern API)

javascript
const obj = {
  name: "test",
  date: new Date(),
  map: new Map([["key", "value"]]),
  arr: [1, 2, 3],
};

const clone = structuredClone(obj);
// ✅ Handles Date, Map, Set, ArrayBuffer, circular references
// ❌ Cannot clone functions or DOM nodes
// ✅ Available in Node.js 17+, modern browsers

Approach 3: Manual Recursive Clone

javascript
function deepClone(obj, map = new WeakMap()) {
  // Handle non-object primitives and null
  if (obj === null || typeof obj !== "object") return obj;

  // Handle circular references
  if (map.has(obj)) return map.get(obj);

  // Handle special types
  if (obj instanceof Date) return new Date(obj);
  if (obj instanceof RegExp) return new RegExp(obj);
  if (obj instanceof Map) {
    const mapClone = new Map();
    map.set(obj, mapClone);
    obj.forEach((v, k) => mapClone.set(deepClone(k, map), deepClone(v, map)));
    return mapClone;
  }

  // Handle plain objects and arrays
  const clone = Array.isArray(obj) ? [] : {};
  map.set(obj, clone);

  for (const key of Reflect.ownKeys(obj)) {
    clone[key] = deepClone(obj[key], map);
  }

  return clone;
}

How to Choose

ScenarioRecommendation
Plain JSON data, no special typesJSON.parse(JSON.stringify(...))
Modern environment, need Date/Map/SetstructuredClone
Need to handle functions, precise controlManual recursive implementation
Production projectUse lodash.cloneDeep

In most business code, JSON.parse(JSON.stringify(...)) is sufficient. Use structuredClone or lodash when you need to handle special types.

MIT Licensed