深拷贝的具体实现方式JS
深拷贝(Deep Copy)是指将一个对象的所有内容完整复制到另一个对象中,而不仅仅是复制对象的引用。也就是说,深拷贝不仅拷贝了对象本身,还会递归地拷贝对象内嵌的所有对象,避免原对象和拷贝对象共享引用。
实现深拷贝的一种常见方法是递归。具体步骤如下:
处理循环引用(拓展)(用这个就好了其他的写法忽略掉)
为避免循环引用导致的栈溢出,可以通过使用 Map
来跟踪已经拷贝过的对象。例如:
function deepCloneWithCycleCheck(obj, map = new Map()) { if (obj === null || typeof obj !== 'object') { return obj; } // 如果已经拷贝过这个对象,则直接返回拷贝的对象,避免循环引用 if (map.has(obj)) { return map.get(obj); } let copy = Array.isArray(obj) ? [] : {}; map.set(obj, copy); for (let key in obj) { if (obj.hasOwnProperty(key)) { copy[key] = deepCloneWithCycleCheck(obj[key], map); } } return copy; }
深拷贝实现的关键点:
- 递归调用:当对象内部存在嵌套对象时,需要对嵌套对象继续递归调用
deepClone
函数,确保每一层的对象都被复制。 - 类型判断:在拷贝过程中,必须首先判断当前值是否是对象或者数组,因为只有对象和数组才需要递归拷贝,而其他类型(如字符串、数字、布尔值等)直接赋值即可。
- 数组处理:对于数组,我们需要遍历数组的每一项,并对每一项进行深拷贝。
- 防止循环引用:这个实现没有处理循环引用问题,如果对象中存在循环引用(如对象的某个属性引用了对象本身),递归会导致栈溢出。为了解决这个问题,需要使用某种方式来追踪已经拷贝过的对象,通常可以借助一个 Map 或 WeakMap 来存储已经处理的对象。
例子
const original = { name: "Alice", age: 25, details: { city: "New York", hobbies: ["reading", "cycling"] } }; const copied = deepClone(original); // 修改复制对象的内容,验证原始对象不受影响 copied.details.city = "Los Angeles"; copied.details.hobbies.push("swimming"); console.log(original.details.city); // New York console.log(original.details.hobbies); // ["reading", "cycling"] console.log(copied.details.city); // Los Angeles console.log(copied.details.hobbies); // ["reading", "cycling", "swimming"]
这样可以处理循环引用,确保深拷贝不会导致无限递归。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现