深拷贝函数的实现
使用JSON.parse(Json.stringify())实现深拷贝有哪些坑?
- 如果属性值是undefined、或者函数,序列化后属性丢失;
- 如果属性值是RegExp、Error对象,序列化后值是{};
- 如果属性值是NaN、Infinity和-Infinity,则序列化的结果会变成null
因此一般都采用自定义函数实现:
function deepClone(obj, map = new WeakMap()) { // 不是对象,直接返回(包括基础数据类型、 `null` 和 `undefined`) if (obj === null || obj === undefined || typeof obj !== "object") return obj; // 避免循环引用 if (map.has(obj)) return map.get(obj); // 处理特殊对象(Date / RegExp) if (obj instanceof Date) return new Date(obj); if (obj instanceof RegExp) return new RegExp(obj); //创建新对象或数组 const cloneObj = Array.isArray(obj) ? [] : {}; // 存入 `WeakMap`,防止循环引用 map.set(obj, cloneObj); //获取所有键,包括 `Symbol` const keys = Reflect.ownKeys(obj); //递归拷贝属性 keys.forEach((key) => { cloneObj[key] = deepClone(obj[key], map); }); return cloneObj; } //测试用例 const obj1 = { num: 1, str: "hello", arr: [1, 2, { a: 3 }], obj: { x: 10 }, date: new Date(), regex: /abc/g, sym: Symbol("sym"), }; obj1.self = obj1; // 🌀 创建循环引用 const clone = deepClone(obj1); console.log(clone); console.log(clone === obj1); // false 证明是深拷贝 console.log(clone.arr === obj1.arr); // false 证明数组被深拷贝 console.log(clone.obj === obj1.obj); // false 证明对象被深拷贝 console.log(clone.date === obj1.date); // false 证明 Date 被拷贝 console.log(clone.regex === obj1.regex); // false 证明 RegExp 被拷贝 console.log(clone.self === clone); // true 证明循环引用正确处理
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现