关于深浅拷贝

用户头像
西贝
关注
发布于: 2020 年 09 月 28 日
关于深浅拷贝



深拷贝和浅拷贝是很常见的操作,但从概念的角度,却很难描述清楚。

先说概念,没有一个平台或文章对深拷贝和浅拷贝的概念提出所谓的标准定义,大都是一段被大多数人认可的常规的描述。



浅拷贝:如果在拷贝这个对象的时候,只对基本数据类型进行了拷贝,而对引用数据类型只是进行了引用的传递,而没有真实的创建一个新的对象。



深拷贝:在对引用数据类型进行拷贝的时候,创建了一个新的对象,并且复制其内的成员变量。



从以上两段描述,可以得出以下几点:

  1. 深浅拷贝都是针对引用数据类型的

  2. 深浅拷贝的区别点在于对内部的引用数据类型的引用方式

  3. 深浅拷贝的返回结果是否是一个新的对象



第一点,深浅拷贝都是针对引用数据类型的。也就是说,深浅拷贝是引用数据类型才有的概念,对于基本数据类型是无所谓深浅拷贝的。所以在实现深浅拷贝的时候,只要检验当前数据是否为引用数据类型即可,如果是引用数据类型,则继续操作,反之,则直接返回即可

function deepCopy (data) {
if (data && typeof data != 'object') {
return data
}
// other code
}



第二点,深浅拷贝的区别点在于对内部的引用数据类型的引用方式。浅拷贝对内部的引用数据类型使用的是同一个引用地址,深拷贝则是创建了一个新的地址,并将引用类型的数据重新拷贝了一份,然后将新的地址引向了新拷贝的数据。以上只是说了针对内部引用类型的数据的操作,而对于内部的基本类型的数据则做了相同的操作,都是新生成了一份新的数据并保存



此处有一点需要注意和说明,是关于浅拷贝和赋值,赋值不等于浅拷贝,很多人可以区别深拷贝和浅拷贝,但经常在浅拷贝和赋值之间混淆



const person = {
name: 'zhangsan',
age: 21,
interest: ['足球', '篮球', '跑步']
}
const person1 = person
person1.name = 'lisi'
console.log(person.name) // lisi



注意第7行 const person1 = person ,此处为赋值,是直接将 person的引用赋值给了 person1,所以当修改 person1name 值时,personname 也发生了变化



const person = {
name: 'zhangsan',
age: 21,
interest: ['足球', '篮球', '跑步']
}
const person1 = {
...person
}
person1.name = 'lisi'
person1.interest.push('羽毛球')
console.log(person.name) // zhangsan
console.log(person.interest) // ['足球', '篮球', '跑步', '羽毛球']



同样注意 7 ~ 9 行,此处使用了 ES6 的扩展运算符,再看输出结果,person.name 的值并没有发生变化,而 person.interest 却发生了变化。此时完成的就是一次浅拷贝



  • 赋值是对引用类型的地址进行赋值,指向的是同一个地址

  • 浅拷贝是对引用类型数据中的引用类型的地址进行的赋值



听上去比较拗口,可以理解为,赋值完成的是对引用类型数据本身的指向,浅拷贝完成的是对引用类型数据中的子引用类型数据的指向,也可以解释为,赋值针对的是引用类型本身,浅拷贝针对的是引用类型内的引用类型,针对的层级不同



第三点,深浅拷贝的返回结果是否是一个新的对象。确切的说,深浅拷贝返回的都是一个新的引用类型数据,不同的是,深拷贝返回的结果和原数据是完全独立的,浅拷贝返回的结果和原数据在带有子引用类型的情况下是有牵连的



如何区分深浅拷贝?凡是不经过特殊处理的,肯定不是深拷贝,但经过特殊处理的,未必是深拷贝。多读几遍,你品,你细品。



何为特殊处理?反向解释就是,不能直接得到结果的处理。例如,上例中的扩展运算符,就不属于特殊处理,所以使用扩展运算符得到的是浅拷贝,再比如数组的 concat 方法,得到的是一个新数组,但对其子元素中的引用类型数据,完成的也是浅拷贝



const aArray = [{a1: 1}]
const bArray = aArray.concat([2])
bArray[0].a1 = 11
console.log(aArray[0].a1) // 11



想要完成深拷贝,必须要经过一些特殊的处理,要么手动编写函数实现,要么调用现成的工具库函数,这也是为什么经常会遇到要求手写深拷贝的试题,至少目前没有提供出直接的方法完成深拷贝



关于深拷贝的实现,网络上有很多,此处不再展开描写。本文主要针对深浅拷贝、赋值的一些理论点进行比较和描述,加深对于深浅拷贝的理解



发布于: 2020 年 09 月 28 日 阅读数: 19
用户头像

西贝

关注

还未添加个人签名 2019.02.15 加入

还未添加个人简介

评论

发布
暂无评论
关于深浅拷贝