因为 o 对象中存在循环引用 o.b,导致无法进行 stringify,所以不能用 JSON.parse(JSON.stringify(o)) 做深拷贝可以考虑使用 lodash 的 _.cloneDeep(o) 函数,支持循环引用深拷贝,原理是使用键值对数组记录每个原对象到拷贝对象的映射,拷贝时递归每个属性,检查数组中是否已存在该属性的拷贝,有就直接取出,没有就创建该属性的拷贝并存储另外可以使用 Map 或 WeakMap 存储原对象到拷贝对象的映射,性能比数组更好参考代码// 支持循环引用深拷贝 const cloneCircular = (o, clones = new WeakMap()) => { if (!o || typeof o != 'object') return o if (clones.has(o)) return clones.get(o) const c = Array.isArray(o) ? [] : {} clones.set(o, c) Object.keys(o).forEach(k => c[k] = cloneCircular(o[k], clones)) return c } const o1 = { a: 1 } o1.b = o1 const o2 = cloneCircular(o1) o2.a = 2 console.log(o1.a, o1 === o1.b) // 1 true console.log(o2.a, o2 === o2.b) // 2 true补一个新出的 Web API structuredClone() 支持循环引用深拷贝
因为
o
对象中存在循环引用o.b
,导致无法进行stringify
,所以不能用JSON.parse(JSON.stringify(o))
做深拷贝可以考虑使用 lodash 的
_.cloneDeep(o)
函数,支持循环引用深拷贝,原理是使用键值对数组记录每个原对象到拷贝对象的映射,拷贝时递归每个属性,检查数组中是否已存在该属性的拷贝,有就直接取出,没有就创建该属性的拷贝并存储另外可以使用
Map
或WeakMap
存储原对象到拷贝对象的映射,性能比数组更好参考代码
补一个新出的 Web API structuredClone() 支持循环引用深拷贝