BRUCE_FEBRUCE_FE

EN/CH Mode

BRUCE_FE JS Interview Notes - Implement Deep Clone Function

Learn how to implement JavaScript deep clone function, handle complex nested objects and circular references, and master the pros and cons of different deep clone solutions and practical applications.

影片縮圖

Lazy to read articles? Then watch videos!

Difference Between Shallow Copy and Deep Copy

In JavaScript, objects are reference types. When we assign an object to another variable, we're actually copying the reference to that object, not the object itself. This is why we need to understand the difference between shallow copy and deep copy.

Shallow Copy

Shallow copy only copies the first level properties of an object. For nested objects or arrays, it still copies their references.

// 淺拷貝示例
const original = { a: 1, b: { c: 2 } };

// 使用 Object.assign 進行淺拷貝
const shallowCopy = Object.assign({}, original);

// 使用展開運算符進行淺拷貝
const spreadCopy = { ...original };

// 修改淺拷貝的嵌套屬性
shallowCopy.b.c = 3;

console.log(original.b.c); // 輸出: 3 (原物件也被修改了!)
console.log(spreadCopy.b.c); // 輸出: 3 (同樣被修改了!)

Deep Copy

Deep copy recursively copies all properties, creating a new object that is completely independent of the original object. Modifying the new object won't affect the original object.

Basic Deep Clone Implementation

Below is a simple deep clone function implementation that can handle basic nested objects and arrays:

function deepClone(obj) {
  // 處理基本類型和 null
  if (obj === null || typeof obj !== 'object') {
    return obj;
  }
  
  // 創建新的物件或陣列
  const copy = Array.isArray(obj) ? [] : {};
  
  // 遞迴複製所有屬性
  for (const key in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, key)) {
      copy[key] = deepClone(obj[key]);
    }
  }
  
  return copy;
}

// 使用範例
const original = {
  a: 1,
  b: {
    c: 2,
    d: [3, 4, { e: 5 }]
  }
};

const cloned = deepClone(original);

// 修改克隆對象的嵌套屬性
cloned.b.c = 10;
cloned.b.d[2].e = 20;

console.log(original.b.c); // 輸出: 2 (原始值保持不變)
console.log(original.b.d[2].e); // 輸出: 5 (原始值保持不變)
console.log(cloned.b.c); // 輸出: 10
console.log(cloned.b.d[2].e); // 輸出: 20

This basic implementation can handle regular objects and arrays, but has several limitations:

  • 1. Cannot handle circular references (will cause stack overflow)
  • 2. Cannot properly handle special objects like Date, RegExp, Map, Set, etc.
  • 3. Does not handle object prototype chain
  • 4. Does not handle non-enumerable properties