JavaScript浅拷贝和深拷贝

浅拷贝和深拷贝的区别

浅拷贝
    let a = 10;
    let b=a;
    a=20
    console.log(b)//10
1,由于a和b基本类型并且都是在栈中的,它们分别进行保存,所以这里输出的b还是10

  2,通过内存可以看出,它们的两个值是独立的,更改其中一个不会影响另外一个。如下图

二,引用类型

    let a=[1,2,3]
    let b=a;
    //这里通过更改a里面的第一个元素
    a[0]=10
    console.log(b)//[10,2,3]
原因:
1,由于是一个引用类型,它存的就不是这个数据,而是一个内存地址;
2,这里声明了一个变量a,但它的值并不是直接存了这个数组,而是内存地址,这个时候它会在堆中开辟一块内存存储这个数据[1,2,3];
3,a里面存放的就是这个地址,变量a就根据这个地址进行查找;
4,接着在声明了一个变量b,由于a和b引用的是同一个内存地址,它们共用了一个数据,不管是修改a还是b,它们之间都会相互影响;

内存原理图是这样的

如果要实现深拷贝,就需要把a里面的数据重新开辟一块内存空间给b,让b在指向这个内存地址,让它们两个之间互相彼此独立即可

有两种简单的方式进行实现,展开运算符或for循环

    let a=[1,2,3]
    //1,使用展开运算符
    //let b=[...a];
    //2,使用for循环
    let b=[]
    for(let i=0;i<a.length;i++){
        b.push(a[i])
    }
    a[0]=30
    console.log(b)//[1,2,3]

实现深拷贝

1,使用JSON

        JSON.stringfy() 其实就是将一个 JavaScript 对象或值转换为 JSON 字符串,最后再用 JSON.parse() 的方法将JSON 字符串生成一个新的对象。一般情况下对普通对象需要进行深拷贝,可以使用这种方法进行深拷贝操作,这种是最简单且代码量最少的深拷贝方法

    function deepClone(target) {
	    //创建JSON格式的字符串
	    let str = JSON.stringify(target);
	    //将JSON字符串转为JS数据
	    let data = JSON.parse(str);
	    return data;
	}

缺点:

1,取不到值为 undefined 的 key;

2,如果对象里有函数,函数无法被拷贝下来;

3,对象直接转变为 date 字符串;

    function deepclone(target){
        let str = JSON.stringify(target)
        let data = JSON.parse(str)
        return data
    }
    let obj={
        name:"张三",
        age:18,
        height:undefined,
        date:new Date(),
        arr:[1,2,3],
        fun:function(){
            console.log(this.name)
        }
    }
    let deep1=deepclone(obj)
    console.log(obj)
    deep1.arr[2]=10
    console.log(deep1)

2,Object.assign()拷贝

当对象中只有一级属性,没有二级属性的时候,此方法可用。但是有二级属性的时候就会失效。
    let obj={
        name:"张三",
        age:18,
        height:undefined,
        date:new Date(),
        arr:[1,2,3,{weight:"180"}],
        fun:function(){
            console.log(this.name)
        }
    }
    let result = Object.assign({},obj)
    result.arr[0]=10
    result.arr[3].weight="190"
    console.log(obj)
    console.log(result)

3,使用递归实现简易的深拷贝

    //实现数组或方法的深拷贝
    let obj={
        name:"张三",
        age:18,
        arr:[1,2,3],
        sun:function(){
            console.log(this.name+''+this.age)
        }
    }
    function deepClone(Data){
        if(typeof Data==='object'&&Data!==null){
            let res = Array.isArray(Data)?[]:{};
            for(let k in Data){
                if(Data.hasOwnProperty(k)){
                    res[k]=deepClone(Data[k])
                }
            }
            return res
        }else{
            return Data
        }
    }

    let deep1=deepClone(obj)
    deep1.name="李四"
    deep1.arr[0]=10
    deep1.sun=function () {
        console.log(this.name)
    }
    deep1.sun()
    console.log(deep1)
    console.log(obj)

最终的返回结果,开辟了两块新的内容,彼此独立互不影响

总结:

1,浅拷贝的是地址指向,原对象修改的时候,新对象的数据也跟着修改,他们指向的是一个对象空间。
2,深拷贝:创建一个一模一样的对象,新对象跟原对象不共享内容(新对象和原对象各自独享内存),修改新对象不会改到原对象。

js中浅拷贝和深拷贝所涉及到的知识点和细节还有很多,这里只做了一个简单的整理。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值