浅拷贝和深拷贝(图文详解)

        前端面试中,面试官经常会提到关于浅拷贝和深拷贝的问题。但是我总是理解于它的表面,面试中再深挖一点就会卡壳,我想把我的理解写下来,希望可以帮助到大家,如果有错误的地方希望大家可以指正,以免误导~

看这篇文章之前,对于赋值的过程大家不了解的可以看我的这一篇文章https://blog.csdn.net/jisuaijicainiao/article/details/140844128?spm=1001.2014.3001.5501

浅拷贝的过程直接举例子说明能更加直观理解

首先说明一下浅拷贝的过程: 浅拷贝会创建一个新对象,并将原始对象的属性逐个复制到这个新对象中。然而,对于引用类型的属性(如对象、数组),浅拷贝只会复制引用,而不是复制引用类型的内容。

let obj1 = {
    'name':'Lili',
    'school':{
        'address':"北京"
    }
}
let obj2 = Object.assign({},obj1)
obj2.name = 'sasa'
obj2.school.address = '上海'
console.log(obj1.name)  //'Lili'
console.log(obj1.school.address)  //'上海'

       上面代码的过程通过图片显示就如下,在未改变obj2任何值之前,内存分配中做了这些操作。浅拷贝就是重新创建了一个对象,把被拷贝对象的属性值都放进了自己的对象中。对于引用类型,值也只是存储了引用地址。

       在改变obj2的属性值之后,如下图所示。因为obj2是在一个新的对象中,所以它的基本类型属性的修改不会影响到obj1。但是对于school属性,它是引用类型存储的是一个对象的地址,它跟obj1的school指向的是相同的一个对象。所以修改obj2就会影响到obj1的值。

 但是还有一种情况就是以下代码

let obj1 = {
    'name':'Lili',
    'school':{
        'address':"北京"
    }
}
let obj2 = Object.assign({},obj1)
obj2.name = 'sasa'
obj2.school = {address:'上海'}
console.log(obj1.name)  //'Lili'
console.log(obj1.school.address)  //'北京'

 图解的话就是下图这样的,obj2修改school属性的值,相当于重新创建了一个对象,在堆内存中重新开辟了一块空间,obj2对象的school属性指向新的对象地址。所以obj1和obj2此时不指向同一块空间,所以并不影响obj1对象。

        浅拷贝的实现方式除了Object.assign()方法【let obj2 = Object.assign({}, obj1)】,还有扩展运算符‘...’【let obj2 = {...obj1}】,还有Array.prototype.slice()通常用于数组拷贝【let arr2 = arr1.slice()】,还有Array.prototype.concat()用于数组拷贝【let arr2 = arr1.concat()】等等。

深拷贝

深拷贝的过程:深拷贝会递归的遍历对象的每个属性,如果属性是基本类型就会直接复制值,如果属性是引用类型,深拷贝就会创建一个新的对象或数组,并递归的复制其中的所有属性。深拷贝后的对象与原对象在内存上是完全独立的。

举例说明

let obj1 = {
  name:'Lili',
  school:{
      address:"北京"
  }
}
let obj2 = JSON.parse(JSON.stringify(obj1))

obj2.name = 'sasa'
obj2.school.address = '上海'
console.log(obj1.name)  //'Lili'
console.log(obj1.school.address)  //'北京'

上面代码的图解过程,根据上述深拷贝的过程,在修改拷贝对象的值之前我们可以得到下图的结果。obj1和obj2是两个完全独立的对象。

        当我们对obj2的属性值进行修改后,如下图所示。obj1是完全不受影响的,无论你怎么修改obj2的值都不会改变obj1的值。

 实现深拷贝的方法除了JSON.pares(JSON.stringify())外【let obj2 = JSON.pares(JSON.stringify())】,还有递归遍历手动复制实现,还可用lodash库的_.cloneDeep()方法【let obj2 = _.cloneDeep(obj1)】

今天就到这里吧~ 继续加油

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值