Skip to content

深拷贝

js
/** 一般递归 */
const deepClone = (obj) => {
  // 1. 判断是否是对象或者数组
  if (obj === null || typeof obj !== 'object') {
    return obj;
  }

  // 2. 创建一个新的对象或数组
  const clone = Array.isArray(obj) ? [] : {};

  // 5. 设置对象的原型
  Object.setPrototypeOf(clone, Object.getPrototypeOf(obj));

  // 3. 遍历对象或数组的每一个属性
  /**
   * for (const key of Object.keys(obj)) 只遍历对象自身的可枚举属性(不包括继承的属性)
   * for (let key in obj) 遍历对象的所有可枚举属性,包括对象原型链上的可枚举属性
   * 根据实际需求选择不同的遍历方式
   */
  for (const key of Object.keys(obj)) {
    clone[key] = deepClone(obj[key]); // 递归拷贝属性
  }

  // 4. 返回新的对象或数组
  return clone;
};

/** 防止循环引用 */
const deepCloneHash = (obj, hash = new WeakMap()) => {
  // 1. 判断是否是对象或者数组 (递归出口)
  if (obj === null || typeof obj !== 'object') {
    return obj;
  }

  // 2. 检查该对象是否已经存在于哈希表中,如果存在,直接从哈希表中取出结果
  if (hash.has(obj)) {
    return hash.get(obj);
  }

  // 3. 创建一个新的对象或数组
  const clone = Array.isArray(obj) ? [] : {};

  // 4. 将新创建的对象添加到哈希表中
  hash.set(obj, clone);

  // 5. 遍历对象或数组的每一个属性
  for (const key of Object.keys(obj)) {
    clone[key] = deepCloneHash(obj[key], hash); // 递归拷贝属性
  }

  // 6. 返回新的对象或数组
  return clone;
};

/* ------------------------- 示例 ------------------------- */
const original = {
  name: 'John',
  age: 30,
  skills: ['JavaScript', 'React'],
  address: {
    city: 'New York',
    zip: '10001',
  },
};

// const copy = deepClone(original);
const copy = deepCloneHash(original);
console.log(copy);