在编程中,我们经常需要对对象进行复制或拷贝操作。针对引用类型的拷贝,可以分为浅拷贝和深拷贝两种方式。本文将介绍这两种拷贝方式,并探讨它们的使用场景及方法。
浅拷贝
浅拷贝是指通过某个方法将一个对象完整地复制一份后,原对象的修改会影响到新的对象。下面是几种常见的浅拷贝方法:
Object.create(obj)
Object.create(obj)
方法会创建一个以 obj
为原型的新对象,新对象将继承 obj
对象的属性和方法。这种方式创建的对象被称为原型继承对象。
你看图片,Object会隐式继承obj对象的东西,它是一个空数组,将obj.name改成小红,但是object.name随着改变 图片如下
Object.assign({},a)
Object.assign()
方法用于将一个或多个源对象的属性复制到目标对象中,并返回目标对象。当我们将空对象作为目标对象传递给 Object.assign()
时,实际上是创建了源对象的一个浅拷贝。
当我改变source.a的值的时候,对象target中的a没发改变但是还有原因的
来在展示一个
你看是不是source.b.name值小明改成小红,target中的也发生改变呢?这个就要说,编译器时,存储引用型数数据要存放在堆里面,而target浅拷贝source的存储地址,当source.b.name中的值发生改变,所以target也会改变,这个是重点。
总结来说,Object.assign({}, source)
方法可以用于创建源对象的浅拷贝。对于嵌套对象或数组,它只会进行浅层复制,因此对于深层嵌套的对象,需要使用其他方法来实现深拷贝。
[].concat(arr)
[].concat(arr)
方法可以用于将一个或多个数组合并成一个新数组,并返回这个新数组。当我们将一个数组作为参数传递给 [].concat()
方法时,实际上是创建了这个数组的一个浅拷贝。
const arr2 = [1, 2, b={name:'小明'}];
const newArr = [].concat(arr2);
arr2[2].name='小红';
console.log(newArr);
[].concat(arr)
方法可以用于将一个或多个数组合并成一个新数组,并返回这个新数组。对于包含对象或其他引用类型数据的数组,需要注意浅拷贝可能会带来的影响。如果需要进行深拷贝,可以使用其他方法来实现。
解构
解构赋值在数组和对象的解构过程中,可以实现浅拷贝的效果。当我们使用解构赋值从一个数组或对象中提取值并赋给新的变量时,新变量将引用原始数组或对象中对应位置的值。
const arr = [1, 2, b={name:'小明'}];
const newArr = [...arr];
arr[2].name='小红'
console.log(newArr)
解构赋值只能实现浅拷贝。如果原数组或对象中的元素是对象或其他引用类型,那么新数组或对象中的对应元素仍然会和原数组或对象中的元素指向同一个内存地址。这意味着,在修改新数组或对象中的元素时,可能会影响到原数组或对象中的对应元素。
arr.toReversed().reverse()
这个方法是数组反转之后,在反转得到了原先的数组,接下来下面展示
const arr = [1, 2, b={name:'小明'}];
const newArr = arr.toReversed().reverse()
arr[2].name='小红'
console.log(newArr)
这个就arr.toReversed().reverse(),浅拷贝的方法
深拷贝
深拷贝是指创建一个完全独立的对象副本,原对象的修改不会影响到新的对象。下面介绍一种常用的深拷贝方法:
JSON.parse(JSON.stringify(obj))
可以将一个对象转换为字符串再转换回对象,从而实现深拷贝。这种方法会创建一个新对象,并复制所有属性和值,包括嵌套的引用类型。然而,需要注意的是,这种方法有两个缺陷:
输出
- 无法处理
undefined
、function
、Symbol
等特殊数据类型,这些数据类型在转换过程中会被忽略。 - 无法处理循环引用,即对象中存在相互引用的情况。在处理循环引用时,会导致栈溢出错误。
因此,在使用JSON.parse(JSON.stringify(obj))
进行深拷贝时,需要注意这两个缺陷,并根据实际情况选择其他方法或进行额外的处理。
综上所述,浅拷贝和深拷贝是针对引用类型的拷贝方式。浅拷贝会复制对象或数组的第一层内容,而深拷贝则会创建一个完全独立的对象副本。根据需求选择适当的拷贝方式可以确保程序的正确运行和数据的安全性。 下期我来教大家手动写适配器 喜欢的来个关注 点赞 这个也是以后写文章的动力所在 谢谢大家能观看我的文章 咱下期在见 拜拜