JS-深拷贝与浅拷贝

拷贝

将一个变量赋值 a 给另一个变量 b
如果a是值类型的数据,赋值后,对b进行修改时,不会对a产生影响。

  let a = 222
        let b = a
        b = 333
        console.log(a);//222
        console.log(b);//333

但是,如果a是引用类型的数据,如对象是引用类型的数据,赋值后,对b进行修改,会对a产生影响
原因是,只是将a的地址赋值给了数组,所以对b进行修改的时候,也相当于对a进行了修改

 let a = {
            a: '123',
            b: '456'
        }
        let b = a
        b.b = 789
        console.log(a); //{a: '123', b: 789}
        console.log(b); //{a: '123', b: 789}

所以,如果在赋值时,不想改变原来的变量,就需要拷贝他的值,而不是他的地址

浅拷贝与深拷贝

浅拷贝:只是拷贝一层,更深层次对象级别的只拷贝了地址
深拷贝:深拷贝就会拷贝多层,即使是嵌套了对象,也会都拷贝出来,内容和原对象一样,更改原对象,拷贝对象不会发生变化

浅拷贝

浅拷贝的方式:

  • 使用for循环实现
  • Object.assign 函数可简单的实现浅拷贝,它是将两个对象的属性叠加后面对象属性会覆盖前面对象同名属性。
  • 使用展开语法也可以实现浅拷贝

Object.assign函数:

var target = { a: 1, b: 1 };
var source1 = { b: 2, c: 2 };
var source2 = { c: 3 };
Object.assign(target, source1, source2);   // {a:1, b:2, c:3}
  • 使用展开语法或Object.assign函数:进行浅拷贝
 let aaa = {
            name: 'xz',
            sex: 'man'
        }
        let bbb = {...aaa
        }
        console.log('bbb', bbb); //bbb {name: 'xz', sex: 'man'}
        let ccc = {}
        Object.assign(ccc, aaa)
        console.log('ccc', ccc); //ccc {name: 'xz', sex: 'man'}
  • 浅拷贝之后拷贝第一层的属性,如果第一层有引用类型的属性,只会拷贝其地址,这样就会对原来的数据造成影响
let obj = {
            xxx: 'xxxx',
            zzz: 'xxxzzzz',
            hobit: {
                sport: 'basketball',
                song: '两只老虎'
            }
        }
        let xx = {}
        for (let key in obj) {
            xx[key] = obj[key]
        }
        console.log(xx);

请添加图片描述
但是如果对xx里的hobit属性进行操作,也会影响到obj
请添加图片描述

深拷贝

利用递归的方法 将 对象里的所有值进行拷贝
判断对象里的属性是不是 object类型,如果是递归调用copy(),不是则直接赋值

let xz = {
            name: 'xiaozhuo',
            lesson: {
                math: 'Math',
                english: 'English'
            },
        }
function copy(obj) {
        let cop = {}
        for (let key in obj) {
        //判断对象里的属性是不是 object类型,如果是递归调用copy(),不是则直接赋值
            cop[key] = typeof obj[key] === 'object' ? copy(obj[key]) : obj[key]
        }
        return cop
    }
let lsy = copy(xz)
 	lsy.lesson.math = 'xxxx'

	 console.log(xz);
	 console.log(lsy);

请添加图片描述

对象里面的属性是数组类型的情况

如果按照上面的方法,会出现将数组类型拷贝成对象类型

  let xz = {
            name: 'xiaozhuo',
            lesson: {
                math: 'Math',
                english: 'English'
            },
            arr: [1, 2, 3, 4, 5]
        }


        function copy(obj) {
            let cop = {}
            for (let key in obj) {
                cop[key] = typeof obj[key] === 'object' ? copy(obj[key]) : obj[key]
            }
            return cop
        }

        let lsy = copy(xz)
        lsy.lesson.math = 'xxxx'

        console.log('xz', xz);
        console.log('lsy', lsy);```

在这里插入图片描述

正确的方法是 在函数里面声明变量的时候,先判断传进来的参数是对象还是数组

  let xz = {
            name: 'xiaozhuo',
            lesson: {
                math: 'Math',
                english: 'English'
            },
            arr: [1, 3, 4, 5, 8]
        }

        function copy_arr(obj) {
            let cop = obj instanceof Array ? [] : {}
           //两种都可以
            // for (let key in obj) {
            //     cop[key] = typeof obj[key] == 'object' ? copy_arr(obj[key]) : obj[key]
            // }

            for (let [k, v] of Object.entries(obj)) {

                cop[k] = typeof v == 'object' ? copy_arr(v) : v

            }
            return cop
        }
        console.log('Object.entries(xz)', Object.entries(xz));
        let lsy = copy_arr(xz)
        lsy.arr[0] = 99999
        console.log('xz', xz);
        console.log('lsy', lsy);

请添加图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值