一、数据类型
数据类型分为:
- 基本数据类型
(String、Number、Boolean、Null、Undefined、Symbol (es6引入的一种类型) )
2.引用数据类型
(Object、Array、Function)。
基本数据类型
基本数据类型特点:直接存储在栈中,存的只是一个数据;
所以双方的值并无直接影响
所以基本数据类型的拷贝都是深拷贝(双方互不影响,没有公用的数据)
引用数据类型
引用数据类型:在栈中存储的是内存地址,然后在堆中开辟一块空间去存储值,根据栈中的地址去堆中找相应的数据
若是直接赋值,则会出现两个值的内存地址一指向同一块堆中的数据,修改一方的数据会影响另一方
二、 浅拷贝
浅拷贝只会拷贝到这个值的内存地址,并不会直接拷贝到他的值,所以会出现两个值拥有相同的内存地址指向同一块堆中的数据,修改值时会相互影响
<script>
let a = [1,2]
let b= a
a[0] = 2
console.log(b);
</script>
被修改了
方法
Object.assign()
展开运算符(…)
但是只针对对象只有简单的一层有效,当对象中嵌套了另一个对象,则拷贝者与被拷贝者也还是会相互影响,所以就用到了深拷贝
三、深拷贝的方法
直接将所有的东西都复制过来,并开辟一个新的栈,两个数据指向不同的内存地址,故修改数据不会相互影响
1.遍历递归
可以通过递归数组,将数据push进另一个空数组里面实现深拷贝
或者使用es6的展开运算符直接在空数组中展开实现赋值
<script>
let a = [1,2]
let b= [...a]
a[0] = 2
console.log(b);
</script>
并未被修改
但是这种方法只会拷贝一层的数据,当数组里面再嵌套一层数据的话,这层数据指向另一块内存空间中的数据,所以当有两层数据的时候,当拷贝第二层数据的时候还是相当于浅拷贝,修改第二层的数据也是会相互影响的
<script>
let a = [1,2,[1,2]]
let b= [...a]
a[2][0] = 2
console.log(b);
</script>
被修改了
2. 通过JSON格式实现多层数组的深拷贝( JSON.parse(JSON.stringify()))
将数组先转为JSON格式的字符串,再转为JSON格式的对象赋值给另一个变量
<script>
let a = [1,2,[1,2]]
let b=JSON.parse(JSON.stringify(a))
a[2][0] = 2
console.log(b);
</script>
未被修改
但是JSON格式对于数据中有函数的情况并不能拷贝过去
<script>
let a={
name:'hhh',
fn(){
console.log(111);
}
}
let b = JSON.parse(JSON.stringify(a))
console.log(a);
console.log(b);
</script>
观察发现,a中的函数b并未拷贝过来
3. 通过lodash实现函数的深拷贝(最完善的方法)
Lodash 通过降低 array、number、objects、string 等等的使用难度从而让 JavaScript 变得更简单。 Lodash 的模块化方法 非常适用于:
遍历 array、object 和 string
对值进行操作和检测
创建符合功能的函数
1.安装
npm i --save lodash
2.引入
import {cloneDeep} from 'lodash'
3.使用
新的变量 = cloneDeep(被拷贝的变量)