深拷贝面试如何回答

一句话回答

深拷贝是指创建一个新对象,并递归复制原对象内部所有引用类型的数据,使新旧对象完全独立。修改拷贝对象中的嵌套数据,不会影响原对象。

对应地,浅拷贝只复制第一层;如果属性值是对象或数组,复制的是引用地址。

const obj = { a: { b: 1 } };
const copy = { ...obj };
 
copy.a.b = 2;
console.log(obj.a.b); // 2,说明这是浅拷贝

常见实现方式

1. JSON 方案

const copy = JSON.parse(JSON.stringify(obj));

优点是简单,适合纯 JSON 数据。

缺点是:

  • 不能处理 undefined、函数、Symbol
  • Date 会变成字符串
  • RegExpMapSet 会丢失结构
  • 不能处理循环引用
  • 原型链会丢失

所以它只适合简单数据结构,不适合通用深拷贝。

2. structuredClone

const copy = structuredClone(obj);

它是现代浏览器和 Node.js 中提供的原生深拷贝 API,支持:

  • 普通对象和数组
  • Date
  • Map
  • Set
  • ArrayBuffer
  • 循环引用

但它不能拷贝函数、DOM 节点等不可结构化克隆的数据。

手写深拷贝思路

面试中如果要求手写,核心点是:

  1. 基本类型直接返回
  2. 引用类型递归复制
  3. WeakMap 解决循环引用
  4. 特殊处理 DateRegExpMapSet
  5. 使用 Reflect.ownKeys 支持 Symbol key
function deepClone(obj, map = new WeakMap()) {
  if (obj === null || typeof obj !== 'object') {
    return obj;
  }
 
  if (obj instanceof Date) {
    return new Date(obj);
  }
 
  if (obj instanceof RegExp) {
    return new RegExp(obj.source, obj.flags);
  }
 
  if (map.has(obj)) {
    return map.get(obj);
  }
 
  if (obj instanceof Map) {
    const result = new Map();
    map.set(obj, result);
 
    obj.forEach((value, key) => {
      result.set(deepClone(key, map), deepClone(value, map));
    });
 
    return result;
  }
 
  if (obj instanceof Set) {
    const result = new Set();
    map.set(obj, result);
 
    obj.forEach(value => {
      result.add(deepClone(value, map));
    });
 
    return result;
  }
 
  const result = Array.isArray(obj) ? [] : {};
  map.set(obj, result);
 
  Reflect.ownKeys(obj).forEach(key => {
    result[key] = deepClone(obj[key], map);
  });
 
  return result;
}

面试总结话术

深拷贝就是递归复制对象中的所有引用类型,让拷贝后的对象和原对象完全独立。简单场景可以用 JSON.parse(JSON.stringify()),但它有很多限制,比如不能处理函数、undefinedDateMapSet 和循环引用。现代环境可以用 structuredClone。如果手写实现,需要判断基本类型、数组、对象以及特殊类型,并且用 WeakMap 解决循环引用问题。