是什么?(定义)
深拷贝:将原来变量的值赋给新变量,但是新变量的改变不会导致原变量的改变,没有关联。
浅拷贝:将原来变量的值赋给新变量,但是新变量的改变会导致原变量的改变,有关联。
为什么使用?(优点)
在JavaScript中有两大类型:简单数据类型(string、number、null、undefined等)和复杂数据类型(object、array等)。
注:简单数据类型是值的直接传参,复杂数据类型是内存地址的传参。
通过深拷贝可以对新变量进行修改,也不会对原变量产生影响。
在哪里使用?(使用场景)
简单数据类型传参:a赋值给b,b修改后不会改变a的值。
复杂数据类型传参:a对象赋值给b,b里的内容修改后会同时改变a的内容,因为复杂数据类型是内存地址的传参,a和b指向都是同一个对象,于是需要进行深拷贝,防止修改新变量而对原变量进行同步修改。
如何使用?(解法)
1、基本思路:开辟一块内存,然后将原对象中的数据全部复制过去,新对象和原对象毫无关系,互不影响。
2、代码实现:
a、常用:通过JSON.parse和JSON.stringify的配套使用(不能深拷贝方法、date对象、正则)。
const a = {
en: 'Bye',
de: 'Tschüss'
}
let b = JSON.parse(JSON.stringify(a))
b.de = 'Ciao'
console.log(b.de) // Ciao
console.log(a.de) // Tschüss
b、只能拷贝浅层:ES6中的扩展运算符 …(不能深拷贝多维数组)。
const a = {
en: 'Bye',
de: 'Tschüss'
}
let b = { ...a }
b.de = 'Ciao'
console.log(b.de) // Ciao
console.log(a.de) // Tschüss
c、Array.from(arr),针对于数组。
const a = ['Bye', 'Tschüss']
let b = Array.from(a)
b[0] = 'Ciao'
console.log(b[0]) // Ciao
console.log(a[0]) // Bye
d、自定义函数,通过递归遍历一个对象的属性(不包括原型链上的属性),赋值给一个空对象,将这个空对象返回。 参考于浅析深度克隆(deepclone) - 知乎 (zhihu.com)。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>深拷贝</title>
</head>
<body>
<script>
var obj = {
a: 1,
b: [1, 2, 3],
c: {
c1: 1
}
}
function deepClone(obj) {
//如果不是对象,直接返回
if (typeof obj !== "object") return obj;
let result;
//判断是不是数组
if (obj instanceof Array) {
result = []
}
else {
result = {}
}
for (const key in obj) {
//判断key是不是自身的属性而不是原型的
if (Object.hasOwnProperty.call(obj, key)) {
//递归
result[key] = deepClone(obj[key])
}
}
return result
}
let obj1 = deepClone(obj);
obj1.b.push(4);
console.log(obj.b, obj1.b);//[1,2,3] [1,2,3,4]
</script>
</body>
</html>