合规国际互联网加速 OSASE为企业客户提供高速稳定SD-WAN国际加速解决方案。 广告
Object.assign 不是深拷贝 是浅拷贝 ## 序列化反序列化实现深拷贝 序列化: JSON.stringify 反序列化: JSON.parse ``` let test = { x: 1, y: 2, z: { a: 4, b: 5 } } let result = JSON.parse(JSON.stringify(test)); result.z.a = 40; console.log(test.z.a) // 4 ``` ### 序列化反序列化拷贝对象时存在的问题 1. 对象的属性在序列化之后不能保证顺序输出 2. undefined、函数以及symbol值都会被忽略 3. 序列化循环引用的对象时,会报错 ![](https://img.kancloud.cn/bb/f7/bbf7d990f1e5e67295e39f97907b35b8_1243x303.png) 4. symbol 类型的属性健会被忽略 5. 不可枚举的属性会被忽略 ![](https://img.kancloud.cn/55/28/55283e60336e36a2467b4f3199e85fbd_1067x291.png) 6. 如果obj中的对象是有构造函数生成的, 则使用JSON.parse(JSON.stringify(obj))深拷贝后,会丢弃对象的constructor; 7. Regexp 和 Error 对象,序列化之后得到的是空对象 ![](https://img.kancloud.cn/e7/d5/e7d5d1f4fe301c126b23f2facaab9c31_950x340.png) 8. Date 类型的数据序列化之后返回的是字符串 ![](https://img.kancloud.cn/b9/1a/b91a4e26b668a0f3088348a113d03d70_885x261.png) ## 手写深拷贝 ``` function copy(obj) { let cloneObj if(obj && typeof obj !== 'object'){ cloneObj = obj return cloneObj }else{ cloneObj = Array.isArray(obj) ? [] : {} for(let key in obj){ if(obj.hasOwnProperty(key)){ if(obj[key] && typeof obj[key] === 'object'){ cloneObj[key] = copy(obj[key]) }else{ cloneObj[key] = obj[key] } } } } return cloneObj } ``` ### 如果需要考虑到 Date、Regexp等数据类型呢 * Regexp 和 Error 对象,序列化之后得到的是空对象 * Date 类型的数据序列化之后返回的是字符串 ``` if(Constructor === Date || Constructor === RegExp){ cloneDeep[key] = new Constructor(obj[key]) } ``` ## 循环引用如何解决 ``` function cloneDeep (obj) { let hash = new Map() function baseClone (target) { if (!isObject(target)) return target if (hash.get(target)) return hash.get(target) let result = Array.isArray ? [] : {} hash.set(target, result) for (let key in target) { result[target[key]] = baseClone(target[key]) } return result } return baseClone(obj) } ```