自己写深拷贝

文章探讨了使用JSON.stringify和JSON.parse进行深拷贝的局限性,包括丢失undefined、函数、日期、正则表达式和NaN等类型,以及处理循环引用的问题。然后介绍了通过递归函数实现的深拷贝方法,以克服上述限制。
摘要由CSDN通过智能技术生成

一、 深拷贝

  • JSON.stringfy() 将对象序列化成json对象
  • JSON.parse() 反序列化——将json对象反序列化成js对象

这个深拷贝是有弊端的(直接上代码)

let copyObj = JSON.parse(JSON.stringify(obj))
    copyObj.a = 2
    console.log(obj, copyObj)

 

 最基础的深拷贝,这样就成功了!

但是会有问题,什么问题呢?

let obj = {
        a:undefined,
        b:{
            c: function() {
                console.log(1)
            },
            d: null,
            e: new Date(),
            f: new RegExp('\\w+'),
            g: NaN
        },
    }

    let copyObj = JSON.parse(JSON.stringify(obj))
    console.log(obj, copyObj)

 1.原对象中的a、c不见了,undefined、function类型的key会丢失
2.e时间对象,会变成字符串形式
3.RegExp定义的属性会变成 {}
4.NaN 类型会变成 null
还有一个问题: 循环引用

let obj = {
        a:1,
    }
    obj.c = obj
    let copyObj = JSON.parse(JSON.stringify(obj))
    console.log(obj, copyObj)

 5.无法处理循环引用的问题
结论:这种拷贝方式局限性比较大,但是在日常开发中一般只是拷贝基本的数据类型,个人在开发中用的还是比较多

二、自己写递归实现深拷贝

function deepCopy(source){
  //json对象 数组 其他类型
  if(Array.isArray(source)){
    let arr = [];
    source.forEach(item=>{
      if(typeof item === 'object'){
        arr.push(deepCopy(item));
      }else{
        arr.push(item);
      }
    })
    return arr;
  }else if(isJson(source)){
    let json = {};
    Object.keys(source).forEach(keyName=>{
      const val = source[keyName];
      if(typeof val === 'object'){
        json[keyName] = deepCopy(val);
      }else{
        json[keyName] = val;
      }
    })

    return json ;
  }else{
    return source;
  }
}

这样就实现了深拷贝!

参考连接:(159条消息) JS实现深拷贝的三种方式_js深拷贝_Make Life Getting Better的博客-CSDN博客

在C/C++中,memcpy是一种内存拷贝函数,它可以将一段内存空间中的内容原封不动地拷贝到另外一段内存空间中。memcpy的拷贝实际上是浅拷贝,也就是说,如果拷贝的是内置类型的元素,memcpy即高效又不会出错,但如果拷贝的是自定义类型元素,并且自定义类型元素中涉及到资源管理时,就会出错。因为浅拷贝只是拷贝了指针,而没有拷贝指针所指向的内存,这样就会导致多个对象共享同一块内存,从而可能会引起内存泄漏甚至程序崩溃。 为了避免这种情况,我们需要使用深拷贝深拷贝是指在拷贝对象时,不仅要拷贝对象本身,还要递归地拷贝对象所包含的所有子对象,直到所有子对象都被拷贝完毕。这样就可以保证每个对象都有自己独立的内存空间,不会相互影响。 在C++中,可以通过拷贝构造函数和赋值运算符来实现深拷贝拷贝构造函数是在创建一个新对象时,以已存在的对象作为参数,使用已存在对象的值来初始化新对象的成员变量。赋值运算符则是在已有对象的基础上,将另一个对象的值赋给该对象。 下面是一个使用拷贝构造函数和赋值运算符实现深拷贝的例子: ```c++ #include <iostream> #include <cstring> using namespace std; class String { public: String(const char* str = nullptr); // 构造函数 String(const String& other); // 拷贝构造函数 ~String(); // 析构函数 String& operator=(const String& other); // 赋值运算符 void print() const; // 打印字符串 private: char* m_data; // 字符串指针 int m_length; // 字符串长度 }; String::String(const char* str) { if (str == nullptr) { m_length = 0; m_data = new char[1]; *m_data = '\0'; } else { m_length = strlen(str); m_data = new char[m_length + 1]; strcpy(m_data, str); } } String::String(const String& other) { m_length = other.m_length; m_data = new char[m_length + 1]; strcpy(m_data, other.m_data); } String::~String() { delete[] m_data; } String& String::operator=(const String& other) { if (this != &other) { delete[] m_data; m_length = other.m_length; m_data = new char[m_length + 1]; strcpy(m_data, other.m_data); } return *this; } void String::print() const { cout << m_data << endl; } int main() { String str1("Hello"); String str2(str1); // 使用拷贝构造函数 String str3 = str1; // 使用赋值运算符 str1.print(); // 输出:Hello str2.print(); // 输出:Hello str3.print(); // 输出:Hello str2 = "World"; // 使用赋值运算符 str2.print(); // 输出:World return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值