利用 JSON 深拷贝的弊端

深拷贝不仅将原对象的各个属性逐个复制出去,而且将原对象各个属性所包含的对象也依次采用深拷贝的方法递归复制到新对象上。

function deepClone(obj){
    return obj_ = JSON.parse(JSON.stringify(obj)),
}
let a=[1,2,3,4,[2,3,4]],
b = deepClone(a);

弊端:

1.如果 obj 里面有时间对象,则 JSON.stringify 后再 JSON.parse 的结果,时间将转为字符串的形式,而不是对象的形式

let obj = {
    a:123,
    b:[new Date(),new Date()]
}
let newObj = JSON.parse(JSON.stringify(obj));
console.log(obj,newObj);

在这里插入图片描述

2.如果 obj 里有 RegExp (正则表达式的缩写)、Error 对象,则序列化的结果将只得到空对象;

let obj = {
    a:123,
    b:/aabb[a-z]\d/,
    c:new TypeError('typeError')
}
let newObj = JSON.parse(JSON.stringify(obj));
console.log(obj,newObj);

在这里插入图片描述

3、如果 obj 里有函数(function),undefined,Symbol 则序列化的结果会把 function 或 undefined 丢失;

let obj = {
    a:123,
    fn:function(){let a = 123;console.log(a)},
    c:undefined,
    d:Symbol('foo')
}
let newObj = JSON.parse(JSON.stringify(obj));
console.log(obj,newObj);

在这里插入图片描述

4、如果obj里有 NaN、Infinity 和 -Infinity,则序列化的结果会变成 null

let obj = {
    a:123,
    b:NaN,
    c:Infinity,
    d:-Infinity
}
let newObj = JSON.parse(JSON.stringify(obj));
console.log(obj,newObj);

在这里插入图片描述

5、JSON.stringify() 只能序列化对象的可枚举的自有属性,例如如果 obj 中的对象是有构造函数生成的, 则使用 JSON.parse(JSON.stringify(obj)) 深拷贝后,会丢弃对象的 constructor;

class Student{
    constructor(){
        this.a = 1;
        this.b = 2;
    }
}
let obj = {
    a:123,
    b:new Student()
}
let newObj = JSON.parse(JSON.stringify(obj));
console.log(obj,newObj);

在这里插入图片描述

手动设置某属性不可枚举:

let obj = {
    a:123,
    b:234
}
Object.defineProperty(obj,'c',{
    value:22,
    enumerable:false,
})
let newObj = JSON.parse(JSON.stringify(obj));
console.log(obj,newObj);

在这里插入图片描述

6、如果对象中存在循环引用的情况也无法正确实现深拷贝;

当存在循环引用的时候,JSON.stringify 会一直去序列化所有对象,包括引用的对象,一直往复会爆栈,所以JSON.stringify 遇到循环引用会直接抛出异常,解决方法,利用一个 map 来存储对象(利用JSON.stringify的第二个参数)

let a = {aaa: 123}
let b = {bbb: 234}
a.child = b
b.parent = a
 
// 声明cache变量,便于匹配是否有循环引用的情况
let cache = []
let res = JSON.stringify(a, function(key, value){
  if (typeof value === 'object' && value !== null) {
    if (cache.includes(value)) {
      // 移除
      return
    }
    // 收集所有对象
    cache.push(value)
  }
  return value
})
// 清空,便于垃圾回收机制回收
cache = null
 
console.log(res) //'{"aaa":123,"child":{"bbb":234}}'

总结:

Date 对象变为字符串 RegExp、Error 对象变为空对象 {} 函数、undefined、Symbol 属性丢失
NaN、Infinity、-Infinity 变为 null enumerable 为 false 的属性丢失 循环引用的对象不能正确拷贝
用法简单,然而使用这种方法会有一些隐藏的坑:因为在序列化 JavaScript 对象时,所有函数和原型成员会被有意忽略。

通俗点说,JSON.parse(JSON.stringfy(X)),其中 X 只能是 Number, String, Boolean,
Array,扁平对象,即那些能够被 JSON 直接表示的数据结构。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
利用JSON.parse实现深拷贝的方法是先使用JSON.stringify将对象序列化为JSON字符串,然后再使用JSON.parse将JSON字符串反序列化为新的对象。这样可以实现对象的深拷贝,即创建一个与原对象完全相同的新对象,而不是共享同一个对象的引用。这种方法适用于大多数情况下的深拷贝需求。\[2\]\[3\]以下是一个示例代码: ```javascript function deepClone(obj) { let newObj = JSON.parse(JSON.stringify(obj)); return newObj; } // 测试 let obj = { name: 'John', age: 25 }; let newObj = deepClone(obj); obj.name = 'Tom'; console.log(obj); // { name: 'Tom', age: 25 } console.log(newObj); // { name: 'John', age: 25 } ``` 在上述代码中,我们定义了一个deepClone函数,它接受一个对象作为参数。函数内部先使用JSON.stringify将对象序列化为JSON字符串,然后再使用JSON.parse将JSON字符串反序列化为新的对象。最后返回这个新对象。通过这个方法,我们可以实现对原对象的深拷贝,即使修改原对象也不会影响到新对象。 #### 引用[.reference_title] - *1* *3* [JSON.parse(JSON.stringify(obj))实现深拷贝](https://blog.csdn.net/weixin_41655541/article/details/111031808)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [JSON.parse(JSON.stringify()) 实现对对象的深拷贝](https://blog.csdn.net/JackieDYH/article/details/127441724)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值