💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
[toc] #### 1.浅拷贝 浅拷贝:拷贝的是对象的指针,修改内容互相影响 深拷贝:整个对象拷贝到另一个内存中,修改内容互不影响 #### 2.深拷贝 方法1:JSON.parse(JSON.stringify) 缺点:以下几种value无法正常拷贝: undefined, NaN, function , Date对象,正则,以及循环引用等 ```js let a = { key1: NaN, // null key2: undefined, // 无 key3: function() { // 无 }, key4: new Date('2020-01-01'), // 转化成时间string key5: new RegExp('\\w+'), // 空对象{} key6: new Error('err') // 空对象 {} } let b = JSON.parse(JSON.stringify(a)) ``` 方法2:手写一个深拷贝 1.基础递归版 ```js // 基础递归版 function clone (target) { if (typeof target === 'object') { let cloneTarget = {} for (let key in target) { cloneTarget[key] = clone(target[key]) } return cloneTarget } else { return target } } ``` 2.考虑数组版(常用版) ``` 1.判断是否是引用类型: 如果不是,则直接 return 2.判断是对象还是,数组 3.用 for in 遍历每一个 key,并将 target 的value赋值给 新的 value 4.赋值value的时候,注意可能value也是一个引用类型,所以需要自调用clone方法,形成递归 5.for in 结束时递归结束 ``` ```js function clone(target) { // 判断是否为引用类型 if (typeof target === 'object') { // 判断是否为数组 let cloneTarget = Array.isArray(target) ? [] : {} for (let key in target) { // 递归 cloneTarget[key] = clone(target[key]) } return cloneTarget } else { return target } } ``` 3.解决循环引用的问题: 遍历如下对象,会陷入无线递归 ```js let obj = { a: 1, b: { a: 123, b: { c: 456, }, d: [1, 2, 3, [4, 5]], }, }; obj[obj] = obj; ``` 解决办法: 1.添加一个map,记录map上是否有target对象,如果有直接return,避免陷入无线递归 2.如果没有则,map.set(target, cloneTarget),然后再遍历递归key上的值 ```js function clone(target, map = new Map()) { // 判断是否为引用类型 if (typeof target === 'object') { // 判断是否为数组 let res = Array.isArray(target) ? [] : {} if (map.has(target)) { return map.get(target) } else { map.set(target, res) } for (let i in target) { res[i] = clone(target[i], map) } return res } else { return target } } ```