进行深克隆的是八大基本数据类型(byte,short,int,long,float,double,char,boolean)
大白话理解一下:就是指将数据拷贝后两者无关联,改变一个不会影响到另一个数值变化。
接下来我们来看看为什么会这样:首先,基础数据类型的存储是直接存储在栈内存中的。如此时有一个变量a,当进行赋值操作b=a时,在栈中会为变量开辟一个新的内存空间来存储b 所以a和b位于两个完全不同的存储空间,只是值相同而已,改变a自然b不会发生变化
深拷贝举例
let a=1;
let b=a;
a=3;
console.log(a)//3
console.log(b)//1
进行浅克隆的一般是数组和对象
继续大白话一下:浅克隆就是数据拷贝后,一方数据变化另一方会跟着变化。
引用数据类型只是把地址存在了栈内存中,真正的数据内容是存放在堆内存中的。而这类数据进行赋值时,复制过去的只是地址(相当于其他语言中的引用)。可以这样想:当我赋值 时,我只是给了你我家的门牌号,所以我们屋子里的东西是相同的,如果我拿走了一样物品,你的屋子里也会缺少这件物品(当然了,我们住在一所房子里)。当我们用obj给obj2赋值时,复制过去的只是obj的地址,所以obj改变后,obj2也跟着改变了。
对象浅拷贝举例
let obj={
name: 'zs',
age: 18,
from: 'china',
}
let obj2=obj;
obj.name="lisi"
console.log(obj)//{name: 'lisi', age: 18, from: 'china'}
console.log(obj2)//{name: 'lisi', age: 18, from: 'china'}
那么现在问题来了,假如我有一个数组或是对象,我就是想要复制一份并让他和原数组/对象毫无关系,应该怎样做呢?我们希望在地址复制过去的同时,在堆内存上为新数据开辟一块空间。
不如先来想想怎么让引用数据类型变成基本数据类型。啊!原来有一个JSON方法实现对象、数组和字符串之间的转换! 我们先将obj变成字符串,再进行字符串的赋值(基本数据类型的赋值,深拷贝),最后再将复制好的字符串变回对象和数组不就成了吗!
在这里小小插入一下JSON的有关内容:
JSON 通常用于与服务端交换数据。在接收服务器数据时一般是字符串。因此,一个常用的方法用来将数据转换成字符串:我们一般只使用他的第一个参数:需要被转换成字符串的数据内容value(通常为对象或数组),对剩下两个参数感兴趣的小伙伴可以自行查阅文档
JSON.stringify(value[, replacer[, space]])
另一个常用的方法是将字符串转换成对象,同样,我们只使用他的第一个参数text传一个合法字符串
JSON.parse(text[, reviver])
接下来我们就可以实现对象的深克隆了:还是上面的张三,只不过这次obj中的name变成李四之后,obj2没有跟着改变了。
let obj={
name: 'zs',
age: 18,
from: 'china',
}
let tem=JSON.stringify(obj)
let obj2=tem;
obj2=JSON.parse(obj2)
obj.name="lisi"
console.log(obj)//{name: 'lisi', age: 18, from: 'china'}
console.log(obj2)//{name: 'zs', age: 18, from: 'china'}
那数组又该怎样操作呢,如果对象中不只是基本数据类型,又该怎样操作呢?通过上面的例子我们可以知道,对象中可能都是基本数据类型,他们以键值对的方式存在,而基本数据类型的复制是深拷贝。当我们想将一个引用数据类型进行深拷贝,只需要把里面所有的值都复制一遍就行了!
接下来我们封装一个实现数据深克隆的函数deepClone:
var obj1 = {
a: 1,
b: {
like: 'eat'
},
arr: ['ad', 11,[1,2,3]]
}
const deepClone = (obj) => {
if (typeof (obj) == "object") {
let res;
console.log("引用数据类型")
if (Array.isArray(obj)) {
res = [];
console.log("数组")
for (val of obj) {
res.push(deepClone( val ))
}
} else {
res = {};
console.log("对象")
for (item in obj) {
res[item]= deepClone(obj[item])
}
}
return res
} else {
console.log("基本数据类型")
return obj
}
}
var obj2 = deepClone(obj1);
obj1.b.like = "drank"
obj1.a="hello"
obj1.arr[2][1]="world"
console.log(obj1)
console.log(obj2)
最后输出的结果如图,让我们来分析一下这个函数是如何执行的:我们创建一个空遍历res用来存储最后的结果。首先obj是一个对象,循环遍历对象中的三个元素,第一个是基本数据类型,将其值obj[item]也就是1递归调用函数作为参数,因为他是基本数据类型,所以直接返回了。第二个元素同样递归后因为是对象,再递归一次变成基本数据类型返回。第三元素...n次递归之后,所有元素都成功在变成基本数据类型之后被复制了。左下输出很清晰的展现了函数的执行过程。