深拷贝面试如何回答
一句话回答
深拷贝是指创建一个新对象,并递归复制原对象内部所有引用类型的数据,使新旧对象完全独立。修改拷贝对象中的嵌套数据,不会影响原对象。
对应地,浅拷贝只复制第一层;如果属性值是对象或数组,复制的是引用地址。
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会变成字符串RegExp、Map、Set会丢失结构- 不能处理循环引用
- 原型链会丢失
所以它只适合简单数据结构,不适合通用深拷贝。
2. structuredClone
const copy = structuredClone(obj);它是现代浏览器和 Node.js 中提供的原生深拷贝 API,支持:
- 普通对象和数组
DateMapSetArrayBuffer- 循环引用
但它不能拷贝函数、DOM 节点等不可结构化克隆的数据。
手写深拷贝思路
面试中如果要求手写,核心点是:
- 基本类型直接返回
- 引用类型递归复制
- 用
WeakMap解决循环引用 - 特殊处理
Date、RegExp、Map、Set - 使用
Reflect.ownKeys支持Symbolkey
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()),但它有很多限制,比如不能处理函数、undefined、Date、Map、Set和循环引用。现代环境可以用structuredClone。如果手写实现,需要判断基本类型、数组、对象以及特殊类型,并且用WeakMap解决循环引用问题。