提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
上节介绍了JavaScript的鼠标事件,这节讲一下JavaScript进阶es6新语法中的拷贝,拷贝是开发场景中常用的操作,这篇将基于新手对拷贝的概念进行讲解,拷贝的实现方式以及使用场景。
一、拷贝
拷贝与复制的作用是一样的,将一个数据类型进行复制,但是拷贝是只针对引用类型来说的,而且复制对引用类型只会单纯的复制其地址值,新的数据名指向的是同一个地址值,那么我们对其复制的数据进行修改时,原本的数据也会被改变,而拷贝不同,是重新开辟出一个新空间,将复制得到数据存进新的空间,因此在对其更改时,原本的数据不会被改变。
根据内存图来区别这两种对引用类型的复制方式
obj1是复制的效果,单纯复制地址值,obj2是拷贝的效果,完全实现了创建一个副本的效果
二、浅拷贝
1.解释
对于该引用类型,浅拷贝会创建一个新的对象,在该引用类型中,如果属性是基本数据类型,会直接复制该属性的值,然后存进新开辟的堆内存空间中,如果属性是引用数据类型,会直接复制其内存地址值,在新开辟的对内存空间中,会指向原来的内存。
2.实现方式
有两种方式实现浅拷贝:(1)o={...obj}(2)Object.assign(o,obj);其中obj为要拷贝的对象,方法一用展开运算符复制对象属性,方法二使用对象的静态方法将要拷贝的对象复制到目标对象中去,且返回目标对象
代码如下(示例):
<script>
// 1.浅拷贝
// 要拷贝的对象
const stu = {
uname: '张三',
age: 18,
subject: '物化生',
family: {
father: '张大三',
mather: '李小四'
}
}
// 方法一:展开运算符
const o = { ...stu }
// 方法二:assign静态方法
Object.assign(o, stu)
console.log(o);
</script>
控制台打印o对象
三、深拷贝
1.解释
我们了解浅拷贝后发现,属性如果是引用类型的话,他只会复制其地址值,那么就会产生和复制一样的问题,我对其属性进行更改的时候,原对象中的引用类型的属性也会跟着改变,因此我们可以用深拷贝解决多层对象的问题。在深拷贝中,如果属性是基本数据类型,直接复制到新开辟的堆内存空间,如果属性是引用类型,在新开辟的堆内存中再开辟一个新的区域存放该引用类型指向的堆内存中的值,类似于嵌套的效果,区域里面又有一个区域,因此,如果其引用类型的属性中还有引用类型,会再次开辟,循环以复。
2.实现方式
有三种实现深拷贝的方法,其中es6本身提供了两种实现深拷贝的方法:利用js库lodash里面的cloneDeep方法,特别注意的是,使用lodash需要导库;还有利用json数据交换格式来实现深拷贝,用到的方法有JSON.stringify();将对象转换成字符串;JSON.parse();将字符串转换为对象,将两者结合使用得到目标对象。
第三种是自己写一个实现深拷贝的封装函数,思路为:接收两个参数,目标对象和要进行拷贝的对象,我写的是没有返回值的,利用for in循环遍历对象的每个属性,用if语句和instanceof运算符判断该属性属于那种类型,这里要注意判断类型的顺序:先判断数组类型再判断对象类型,最后判断是否为基本数据类型,因为数组类型也是对象类型,如果先判断对象类型,那么数组类型会被误判成对象类型;两者都属于引用类型,嵌套的效果,用递归函数的方法再次调用我们写的拷贝函数,那么会再对这个属性进行遍历,直到都为基本数据类型。
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>
<script>
// 2.深拷贝
// 要拷贝的对象
const stu = {
uname: '张三',
age: 18,
subject: '物化生',
family: {
father: '张大三',
mather: '李小四'
}
}
// 1.利用js库lodash的cloneDeep方法
const o = _.cloneDeep(stu)
console.log(o);
// 2.利用JSON的parse和stringify方法
const o1 = JSON.parse(JSON.stringify(stu))
console.log(o1);
// 3.封装深拷贝的函数
function deepCopy(newObj, oldObj) {
// forin循环遍历旧对象,将旧对象的属性值赋值给新对象
for (const k in oldObj) {
// 处理数组问题,判断该属性是否是数组,是的话,可以再次调用拷贝函数,将数组中的值拷贝出来
if (oldObj[k] instanceof Array) {
newObj[k] = []
deepCopy(newObj[k], oldObj[k])
} else if (oldObj[k] instanceof Object) {
// 处理对象问题,判断该属性是否是对象,是的话,可以再次调用拷贝函数,将对象中的值拷贝出来
newObj[k] = {}
deepCopy(newObj[k], oldObj[k])
}
else {
newObj[k] = oldObj[k]
}
}
}
const o2 = {}
deepCopy(o2, stu)
console.log(o2);
</script>
控制台打印效果
总结:
今天的文章分享到这里就结束了,主要对拷贝进行了一个大概的讲解,和介绍了实现拷贝方式,拷贝是我们在进行开发时经常用到的内容,应用场景:对数组和对象的复制,可以储存用户的编辑记录等,对后台的数据进行处理,在组件之间传递数据,可以保护原本的数据不被篡改,可以克隆一个新对象作为原对象的副本。希望大家看过之后有问题及时指正出来哦