浅拷贝和深拷贝

定义一个对象构造函数

        function User (username, password, age, address) {
            this.username = username;
            this.password = password;
            this.age = age;
            this.address = address;
        }

定义一个方法:将对象转化为JOSN字符串输出

        const getJosnString = (obj) =>{
            console.log(JSON.stringify(obj));
        }

浅拷贝

使用 “=” 直接赋值

*使用 = 直接赋值会直接赋值对象的引用

* 假设originalObj对象的地址为 -> 0x0001

* 通过 = 直接把originalObj对象赋值给shallowCopyObj对象

* originalObj对象的地址 -> 0x0001

* shallowCopyObj对象的地址 -> 0x0001

* 两个对象的引用是一样,使用无论对哪个对象属性进行更改的时候,两个对象中属性值都会发生改变

        //浅拷贝    使用 = 直接赋值
        (() => {
            /**
             * 使用 = 直接赋值会直接赋值对象的引用
             * 假设originalObj对象的地址为    ->  0x0001
             * 通过 = 直接把originalObj对象赋值给shallowCopyObj对象
             * originalObj对象的地址        ->  0x0001
             * shallowCopyObj对象的地址     ->  0x0001
             * 两个对象的引用是一样,使用无论对哪个对象属性进行更改的时候,两个对象中属性值都会发生改变
            */

            const originalObj = new User('wang', '123321', 123, {gz: '广州',sz: '深圳',sh: '上海'} ) ;
            const shallowCopyObj = originalObj ;

            //true
            console.log(originalObj === shallowCopyObj );

            //true
            console.log(originalObj.address === shallowCopyObj.address);

            //输出原对象和拷贝的对象
            //{"username":"wang","password":"123321","age":123,"address":{"gz":"广州","sz":"深圳","sh":"上海"}}
            getJosnString(originalObj)

            //{"username":"wang","password":"123321","age":123,"address":{"gz":"广州","sz":"深圳","sh":"上海"}}
            getJosnString(shallowCopyObj)

            //对原对象的基本数据类型age属性进行更改
            originalObj.age = 20;
            //{"username":"wang","password":"123321","age":20,"address":{"gz":"广州","sz":"深圳","sh":"上海"}}
            getJosnString(originalObj)

            //{"username":"wang","password":"123321","age":20,"address":{"gz":"广州","sz":"深圳","sh":"上海"}}
            getJosnString(shallowCopyObj)

            //对拷贝后的对象的基本数据类型age属性进行更改
            shallowCopyObj.age = 40
            //{"username":"wang","password":"123321","age":40,"address":{"gz":"广州","sz":"深圳","sh":"上海"}}
            getJosnString(originalObj)

            //{"username":"wang","password":"123321","age":40,"address":{"gz":"广州","sz":"深圳","sh":"上海"}}
            getJosnString(shallowCopyObj)

            //修改原对象引用数据类型address属性
            originalObj.address.gz = '白云'
            //{"username":"wang","password":"123321","age":40,"address":{"gz":"白云","sz":"深圳","sh":"上海"}}
            getJosnString(originalObj)

            //{"username":"wang","password":"123321","age":40,"address":{"gz":"白云","sz":"深圳","sh":"上海"}}
            getJosnString(shallowCopyObj)
            
            //修改拷贝后对象引用数据类型address属性
            shallowCopyObj.address.gz = '天河'
            //{"username":"wang","password":"123321","age":40,"address":{"gz":"天河","sz":"深圳","sh":"上海"}}
            getJosnString(originalObj)

            //{"username":"wang","password":"123321","age":40,"address":{"gz":"天河","sz":"深圳","sh":"上海"}}
            getJosnString(shallowCopyObj)
        })();

使用Object.assign(a, b)方法

* 使用Object.assign(a, b)方法实现浅拷贝的时候

* js中会创建一个新的对象,将新对象的地址赋值给shallowCopyObj对象

* 假如 originalObj -> 0x0001

* 即使用Object.assign(a, b)方法实现浅拷贝后

* originalObj -> 0x0001

* shallowCopyObj -> 0x0002

*

*         0x0001 -> {

*                                 username: "wang",

*                                 password: "123321",

*                                 age: 123,

*                                 address: -> 0x0003

*                         }

*

*         0x0002 -> {

*                                 username: "wang",

*                                 password: "123321",

*                                 age: 123,

*                                 address: -> 0x0003

*                         }

*

*         0x0003 -> {

*                                 gz: '广州',

*                                 sz: '深圳',

*                                 sh: '上海'

*                         }

* 当我们修改两个对象中基本数据类型age时,两个对象的值时互不影响的

* 当我们修改两个对象中引用数据类型属性address时,因为他们指向的地址是一致的,两个对象都会影响

//浅拷贝    Object.assign(a, b)方法     将 b 对象拷贝给 a 对象      返回值拷贝后的对象
        (() => {
            /**
             * 使用Object.assign(a, b)方法实现浅拷贝的时候
             * js中会创建一个新的对象,将新对象的地址赋值给shallowCopyObj对象
             * 假如 originalObj -> 0x0001
             * 即使用Object.assign(a, b)方法实现浅拷贝后
             *      originalObj         -> 0x0001
             *      shallowCopyObj      -> 0x0002
             * 
             *      0x0001 -> {
             *                  username: "wang",
             *                  password: "123321",
             *                  age: 123,
             *                  address: -> 0x0003              
             *                  }
             * 
             *      0x0002 -> {
             *                  username: "wang",
             *                  password: "123321",
             *                  age: 123,
             *                  address: -> 0x0003              
             *                  }
             * 
             *      0x0003 -> {
             *                  gz: '广州',
             *                  sz: '深圳',
             *                  sh: '上海'         
             *                  }
             * 当我们修改两个对象中基本数据类型age时,两个对象的值时互不影响的
             * 当我们修改两个对象中引用数据类型属性address时,因为他们指向的地址是一致的,两个对象都会影响
             * 
            */

            const a ={
                username: "wang",
                password: "123321",
            }

            const b = {
                age: 21,
                address: {}
            }

            const c = Object.assign(a, b)
            //{"username":"wang","password":"123321","age":21,"address":{"gz":"广州","sz":"深圳","sh":"上海"}}
            getJosnString(a)

            //{"age":21,"address":{"gz":"广州","sz":"深圳","sh":"上海"}}
            getJosnString(b)

            //{"username":"wang","password":"123321","age":21,"address":{"gz":"广州","sz":"深圳","sh":"上海"}}
            getJosnString(c)

            const originalObj = new User('wang', '123321', 123, {gz: '广州',sz: '深圳',sh: '上海'} ) ;
            const shallowCopyObj = Object.assign({}, originalObj) ;

            //false
            console.log(originalObj === shallowCopyObj);

            //true
            console.log(originalObj.address === shallowCopyObj.address);

            //输出原对象和拷贝后的对象
            //{"username":"wang","password":"123321","age":123,"address":{"gz":"广州","sz":"深圳","sh":"上海"}}
            getJosnString(originalObj)

            //{"username":"wang","password":"123321","age":123,"address":{"gz":"广州","sz":"深圳","sh":"上海"}}
            getJosnString(shallowCopyObj)

            //对原对象的基本数据类型age属性进行更改
            originalObj.age = 20;
            //{"username":"wang","password":"123321","age":20,"address":{"gz":"广州","sz":"深圳","sh":"上海"}}
            getJosnString(originalObj)

            //{"username":"wang","password":"123321","age":123,"address":{"gz":"广州","sz":"深圳","sh":"上海"}}
            getJosnString(shallowCopyObj)

            //对拷贝后的对象的基本数据类型age属性进行更改
            shallowCopyObj.age = 40
            //{"username":"wang","password":"123321","age":20,"address":{"gz":"广州","sz":"深圳","sh":"上海"}}
            getJosnString(originalObj)

            //{"username":"wang","password":"123321","age":40,"address":{"gz":"广州","sz":"深圳","sh":"上海"}}
            getJosnString(shallowCopyObj)

            //修改原对象引用数据类型address属性
            originalObj.address.gz = '白云'
            //{"username":"wang","password":"123321","age":20,"address":{"gz":"白云","sz":"深圳","sh":"上海"}}
            getJosnString(originalObj)

            //{"username":"wang","password":"123321","age":40,"address":{"gz":"白云","sz":"深圳","sh":"上海"}}
            getJosnString(shallowCopyObj)
            
            //修改拷贝后对象引用数据类型address属性
            shallowCopyObj.address.gz = '天河'
            //{"username":"wang","password":"123321","age":20,"address":{"gz":"天河","sz":"深圳","sh":"上海"}}
            getJosnString(originalObj)

            //{"username":"wang","password":"123321","age":40,"address":{"gz":"天河","sz":"深圳","sh":"上海"}}
            getJosnString(shallowCopyObj)
        })();

深拷贝

JOSN.parse(JOSN.stringify())方法

* 使用JOSN.parse(JOSN.stringify(obj))方法实现深拷贝时

* js中会创建一个新的对象,将新对象的地址赋值给deepCopyObj对象

* 假如 originalObj -> 0x0001

* 即使用JOSN.parse(JOSN.stringify(obj))方法实现浅拷贝后

* originalObj -> 0x0001

* shallowCopyObj -> 0x0002

*

*                 0x0001 -> {

*                                 username: "wang",

*                                 password: "123321",

*                                 age: 123,

*                                 address: -> 0x0003

*                         }

*

*                        0x0002 -> {

*                                 username: "wang",

*                                 password: "123321",

*                                 age: 123,

*                                 address: -> 0x0004

*                         }

*

*                         0x0003 -> {

*                                 gz: '广州',

*                                 sz: '深圳',

*                                 sh: '上海'

*                         }

*

*                 0x0004 -> {

*                                 gz: '广州',

*                                 sz: '深圳',

*                                 sh: '上海'

*                         }

*

* 当我们修改两个对象中基本数据类型age时,两个对象的值时互不影响的

* 当我们修改两个对象中引用数据类型属性address时,因为他们指向的地址是一致的,两个对象的值时互不影响

*

* 通过这个方法可以实现深拷贝,但是这个方法是不值得推荐的

* 原因:

* 1、无法拷贝特殊对象:JSON.stringify() 方法默认会忽略掉一些特殊对象的属性,

* 例如函数、正则表达式、Symbol 等。这意味着通过 JSON.parse(JSON.stringify(obj))

* 无法完全拷贝包含这些特殊对象的对象。

* 2、无法处理循环引用:如果对象存在循环引用(即对象内部存在相互引用关系),

* 则 JSON.stringify() 会报错,因为 JSON 格式不支持循环引用。

* 因此,这种方式无法正确处理包含循环引用的对象。

* 3、丢失原型链:通过 JSON.parse(JSON.stringify(obj))

* 深拷贝的对象会失去原型链上的信息。拷贝后的对象的原型将变成 Object.prototype,

* 而不再是原始对象的原型。

* 4、效率问题:将对象转换为 JSON 字符串,然后再解析成对象的过程是相对耗时的操作,

* 特别是对于大型对象或嵌套层次很深的对象,会带来性能上的损耗

*

* 推荐使用lodash.js中的cloneDeep()方法可以解决以上问题

//使用JOSN.parse(JOSN.stringify(obj))方法实现深拷贝     返回值为拷贝后的对象
        (() => {
            /**
             * 使用JOSN.parse(JOSN.stringify(obj))方法实现深拷贝时
             * js中会创建一个新的对象,将新对象的地址赋值给deepCopyObj对象
             * 假如 originalObj -> 0x0001
             * 即使用JOSN.parse(JOSN.stringify(obj))方法实现浅拷贝后
             *      originalObj         -> 0x0001
             *      shallowCopyObj      -> 0x0002
             * 
             *      0x0001 -> {
             *                  username: "wang",
             *                  password: "123321",
             *                  age: 123,
             *                  address: -> 0x0003              
             *                  }
             * 
             *      0x0002 -> {
             *                  username: "wang",
             *                  password: "123321",
             *                  age: 123,
             *                  address: -> 0x0004              
             *                  }
             * 
             *      0x0003 -> {
             *                  gz: '广州',
             *                  sz: '深圳',
             *                  sh: '上海'         
             *                  }
             * 
             *      0x0004 -> {
             *                  gz: '广州',
             *                  sz: '深圳',
             *                  sh: '上海'         
             *                  }
             * 
             * 当我们修改两个对象中基本数据类型age时,两个对象的值时互不影响的
             * 当我们修改两个对象中引用数据类型属性address时,因为他们指向的地址是一致的,两个对象的值时互不影响
             * 
             * 通过这个方法可以实现深拷贝,但是这个方法是不值得推荐的
             * 原因:
             *  1、无法拷贝特殊对象:JSON.stringify() 方法默认会忽略掉一些特殊对象的属性,
             *  例如函数、正则表达式、Symbol 等。这意味着通过 JSON.parse(JSON.stringify(obj)) 
             *  无法完全拷贝包含这些特殊对象的对象。
             *  2、无法处理循环引用:如果对象存在循环引用(即对象内部存在相互引用关系),
             *  则 JSON.stringify() 会报错,因为 JSON 格式不支持循环引用。
             *  因此,这种方式无法正确处理包含循环引用的对象。
             *  3、丢失原型链:通过 JSON.parse(JSON.stringify(obj)) 
             *  深拷贝的对象会失去原型链上的信息。拷贝后的对象的原型将变成 Object.prototype,
             *  而不再是原始对象的原型。
             *  4、效率问题:将对象转换为 JSON 字符串,然后再解析成对象的过程是相对耗时的操作,
             *  特别是对于大型对象或嵌套层次很深的对象,会带来性能上的损耗
             * 
             * 推荐使用lodash.js中的cloneDeep()方法可以解决以上问题
             * 
            */      

            const originalObj = new User('wang', '123321', 123, {gz: '广州',sz: '深圳',sh: '上海'} ) ;
            const deepCopyObj = JSON.parse(JSON.stringify(originalObj));

            //false
            console.log(originalObj === deepCopyObj);

            //false
            console.log(originalObj.address === deepCopyObj.address);

            //输出原对象和拷贝后的对象
            //{"username":"wang","password":"123321","age":123,"address":{"gz":"广州","sz":"深圳","sh":"上海"}}
            getJosnString(originalObj)

            //{"username":"wang","password":"123321","age":123,"address":{"gz":"广州","sz":"深圳","sh":"上海"}}
            getJosnString(deepCopyObj)

            //对原对象的基本数据类型age属性进行更改
            originalObj.age = 20;
            //{"username":"wang","password":"123321","age":20,"address":{"gz":"广州","sz":"深圳","sh":"上海"}}
            getJosnString(originalObj)

            //{"username":"wang","password":"123321","age":123,"address":{"gz":"广州","sz":"深圳","sh":"上海"}}
            getJosnString(deepCopyObj)

            //对拷贝后的对象的基本数据类型age属性进行更改
            deepCopyObj.age = 40
            //{"username":"wang","password":"123321","age":20,"address":{"gz":"广州","sz":"深圳","sh":"上海"}}
            getJosnString(originalObj)

            //{"username":"wang","password":"123321","age":40,"address":{"gz":"广州","sz":"深圳","sh":"上海"}}
            getJosnString(deepCopyObj)

            //修改原对象引用数据类型address属性
            originalObj.address.gz = '白云'
            //{"username":"wang","password":"123321","age":20,"address":{"gz":"白云","sz":"深圳","sh":"上海"}}
            getJosnString(originalObj)

            //{"username":"wang","password":"123321","age":40,"address":{"gz":"广州","sz":"深圳","sh":"上海"}}
            getJosnString(deepCopyObj)
            
            //修改拷贝后对象引用数据类型address属性
            deepCopyObj.address.gz = '天河'
            //{"username":"wang","password":"123321","age":20,"address":{"gz":"白云","sz":"深圳","sh":"上海"}}
            getJosnString(originalObj)

            //{"username":"wang","password":"123321","age":40,"address":{"gz":"天河","sz":"深圳","sh":"上海"}}
            getJosnString(deepCopyObj)
            
            //ƒ Object() { [native code] }
            console.log(deepCopyObj.__proto__.constructor);
        })();

lodash.js中_.cloneDeep()方法

        //使用lodash.js中_.cloneDeep()方法
        (() => {
            const originalObj = new User('wang', '123321', 123, {gz: '广州',sz: '深圳',sh: '上海'} ) ;
            const deepCopyObj = _.cloneDeep(originalObj);

            //false
            console.log(originalObj === deepCopyObj);

            //false
            console.log(originalObj.address === deepCopyObj.address)

            //输出原对象和拷贝后的对象
            //{"username":"wang","password":"123321","age":123,"address":{"gz":"广州","sz":"深圳","sh":"上海"}}
            getJosnString(originalObj)

            //{"username":"wang","password":"123321","age":123,"address":{"gz":"广州","sz":"深圳","sh":"上海"}}
            getJosnString(deepCopyObj)

            //对原对象的基本数据类型age属性进行更改
            originalObj.age = 20;
            //{"username":"wang","password":"123321","age":20,"address":{"gz":"广州","sz":"深圳","sh":"上海"}}
            getJosnString(originalObj)

            //{"username":"wang","password":"123321","age":123,"address":{"gz":"广州","sz":"深圳","sh":"上海"}}
            getJosnString(deepCopyObj)

            //对拷贝后的对象的基本数据类型age属性进行更改
            deepCopyObj.age = 40
            //{"username":"wang","password":"123321","age":20,"address":{"gz":"广州","sz":"深圳","sh":"上海"}}
            getJosnString(originalObj)

            //{"username":"wang","password":"123321","age":40,"address":{"gz":"广州","sz":"深圳","sh":"上海"}}
            getJosnString(deepCopyObj)

            //修改原对象引用数据类型address属性
            originalObj.address.gz = '白云'
            //{"username":"wang","password":"123321","age":20,"address":{"gz":"白云","sz":"深圳","sh":"上海"}}
            getJosnString(originalObj)

            //{"username":"wang","password":"123321","age":40,"address":{"gz":"广州","sz":"深圳","sh":"上海"}}
            getJosnString(deepCopyObj)

            //修改拷贝后对象引用数据类型address属性
            deepCopyObj.address.gz = '天河'
            //{"username":"wang","password":"123321","age":20,"address":{"gz":"白云","sz":"深圳","sh":"上海"}}
            getJosnString(originalObj)

            //{"username":"wang","password":"123321","age":40,"address":{"gz":"天河","sz":"深圳","sh":"上海"}}
            getJosnString(deepCopyObj)

            /**
             * ƒ User (username, password, age, address) {
                this.username = username;
                this.password = password;
                this.age = age;
                this.address = address;
                }
            */
            console.log(deepCopyObj.__proto__.constructor);
        })();

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hz没头脑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值