一直以来倒是没有仔细的思考过深浅拷贝的问题,最近有听到小伙伴在讨论,全面了解了一下,深拷贝并没有那么简单。现在让我们来一起探讨深浅拷贝相关的内容吧。
基本数据类型、引用数据类型
为什么会出现深浅拷贝的问题,主要因为在于js中所有的数据类型分为基本数据类型和引用数据类型两大类。
那么基本数据类型有哪些呢:Number
、String
、Boolean
、Undefined
、Null
、Symbol
、BigInt
引用数据类型,就是Object
了,但是js封装了几个继承了Object
原型属性的一些对象,Array
、Function
、Data
、Error
、Map
、Set
等
基本数据类型与引用数据类型的区别
存储方式
基本数据类型和引用数据类型是根据存储方式划分的。基本数据类型在内存中占据固定大小,保存在栈内存中。引用数据类型的值是对象,保存在堆内存中,并会在栈内存中存储该对象的变量标识符以及对象在堆内存中的存储地址。
赋值方式
所以在使用基本数据类型和引用数据类型的时候,关于赋值问题就需要多多思量了。
基本数据类型
基本数据类型的赋值方式,是从一个变量向另一个新变量复制基本类型的值,会创建这个值的一个副本,并将该副本赋值给新变量。
let a = 2;
let b = a;
console.log(a)
console.log(b)
// 修改b的值不会影响a的值
b = 3;
console.log(a)
console.log(b)
引用数据类型
引用数据类型从一个变量向另一个新变量复制引用数据类型的地址,将新复制的地址赋值给新变量,最终两个变量存储的是相同的地址,指向的是堆内存中同一块存储空间。通过一个变量修改对象属性,就会影响另一个变量指向的对象内容。
let c = {
a: 1,
b: 2,
c: 3
}
let d = c
c.c = 5
console.log(d.c)
我们可以看到,通过c变量去修改该对象的c属性,d变量会被影响。那么引用数据类型的这种赋值方式就会对我们的开发造成一定影响。如果我们只想要一个和当前对象一样的对象,但修改数据时不会互相影响,这时候该怎么办呢?
深拷贝、浅拷贝
根据前面讲到的一些简单的知识普及,大家应该都知道了,所谓的深浅拷贝一定是针对于引用数据类型来说的,那么什么是深浅拷贝呢?
- 浅拷贝:仅仅是复制了引用,彼此之间的操作会相互影响,指向的是同一块堆内存空间。前面讲到的=赋值就是浅拷贝。
- 深拷贝:在堆中重新分配内存,不同的地址,相同的值,互不影响。
JavaScript中的拷贝
讲到了深浅拷贝,一定会有些疑问,js中有不少的拷贝方法,那么这些方法它们。。。到底是深拷贝还是浅拷贝。毕竟如果连这都搞不懂,在用的时候就很容易出一些乌龙事件。
concat
concat
,用于连接两个或多个数组。
concat
,方法不会更改现有数组,而是返回一个新数组,其中包含已连接数组的值。
看定义应该是深拷贝,我们可以来测试一下:
let a = [1,2,3,5,6]
let b = [7,8,9]
let c = a.concat(b)
console.log(c) //[1, 2, 3, 5, 6, 7, 8, 9]
a[0] = 2;
console.log(a) //[2,2,3,5,6]
console.</