JavaScript中深拷贝的几种方法

关于深拷贝和浅拷贝的概念---(引用关系)

深拷贝:

1、cpu在堆内存中重新开辟一个存储空间,用于储存这个完全克隆一个一模一样的对象;

2、在栈中会存储一个引用地址,用来指向新开辟的堆内存内容;

3、改变原对象,新对象不会改变;

浅拷贝:

1、不在堆内存中重新开辟空间,只复制拷贝对象栈内存中的引用地址。

2、改变原对象,新对象会改变;

3、本质上两个对象(数组)依然指向堆内存的同一块存储空间;

一、手动递归-遍历对象来拷贝

<!DOCTYPE html>
<html>
    <head></head>
    <body></body>
    <script >
            function deepCopy(obj) {
                //typeof 数组,正则,日期,一般对象 都为object
                if (typeof obj !== 'object' || obj === null) {
                    return obj;
                }

                // 1、处理日期对象
                if (obj instanceof Date) {
                    // const copy = new Date();
                    // copy.setTime(obj.getTime());
                    // return copy;
                    return obj;
                }
                
                // 2、处理正则表达式对象
                if (obj instanceof RegExp) {
                    // const flags = [];
                    // if (obj.global) flags.push('g');
                    // if (obj.ignoreCase) flags.push('i');
                    // if (obj.multiline) flags.push('m');
                    // return new RegExp(obj.source, flags.join(''));
                    return obj;
                }
            


                //3、区分对象和数组,初始化进行赋值
                let copy = Array.isArray(obj) ? [] : {};
                for (let key in obj) {
                    if (obj.hasOwnProperty(key)) {
                    copy[key] = deepCopy(obj[key]);
                    }
                }

                return copy;
            }

          let aaa = {
            a:/^[0-9]+$/,
            b:{
                c: new Date(),
                d: [1,2,3]
            }
          }

          deepCopy(aaa);

          let bbb = deepCopy(aaa)
          console.log('deepCopy',bbb,aaa)
          // bbb    
          // {
          //     a:/^[0-9]+$/,
          //     b:{
          //         c: new Date(),
          //         d: [1,2,3]
          //     }
          // }

          // bbb    
          // {
          //     a:/^[0-9]+$/,
          //     b:{
          //         c: new Date(),
          //         d: [1,2,3]
          //     }
          // }
    </script>
</html>

二、JSON序列化和反序列化,JSON.stringify()和JSON.parse()

let obj = { a: 111, b: { c: 333 } };
let copyObj = JSON.parse(JSON.stringify(obj));
console.log(copyObj); // { a: 111, b: { c: 333 } }

该方法的坑:

1、丢失特定类型信息:正则,日期 作为属性值无法被拷贝,日期会变成字符串,正则在拷贝中直接转换为空对象;

2、无法拷贝函数和对象深度引用;

3、对象中属性值为undefined时会直接被忽略,做空值处理;

4、性能比较低;

三、使用第三方库(lodash)

const _ = require('lodash');

let obj = { a: 111, b: { c: 333 } };
let copyObj = _.cloneDeep(obj);
console.log(copyObj); // { a: 111, b: { c: 333 } }

四、jquery也有个深度拷贝方法

五、三点占位解析符,和Object.assign()方法不是用来拷贝的并且也不满足深度拷贝;

三点解构和Object.assign(),不是深度拷贝操作,它只是提取数据。浅拷贝和深拷贝是拷贝操作,前者只拷贝一层,下图中改变aaa属性中的c,bbb属性中的c也会被改变;

<!DOCTYPE html>
<html>
    <head></head>
    <body></body>
    <script >
            
          let aaa = {
            a:/^[0-9]+$/,
            b:{
                c: new Date(),
                d: [1,2,3]
            }
          }

          let bbb = {
            ...aaa
          }

          
          console.log('deepCopy',bbb,aaa)
          //bbb
            //   {
            //     a:/^[0-9]+$/,
            //     b:{
            //         c: new Date(),
            //         d: [1,2,3]
            //     }
            //   }
          //aaa
            //   {
            //     a:/^[0-9]+$/,
            //     b:{
            //         c: new Date(),
            //         d: [1,2,3]
            //     }
            //   }

          

          aaa.a = "xxx"
          aaa.b.c = "999"
        
          
          console.log('deepCopy',bbb,aaa)
            //bbb
            //   {
            //     a:/^[0-9]+$/,
            //     b:{
            //         c: 999,
            //         d: [1,2,3]
            //     }
            //   }
              //aaa
            //   {
            //     a:xxx,
            //     b:{
            //         c: 999,
            //         d: [1,2,3]
            //     }
            //   }

    </script>
</html>

  • 7
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值