先记住两句话,帮助你简单理解一下深拷贝和浅拷贝的区别:
1 深拷贝拷贝后,产生数据是两条数据
2 浅拷贝拷贝后,多个变量共用一条数据
下面,我们来看个例子:
var a = [1,2,3];
var a1 = a;
a1[0] = 2;
console.log(a); // ==>Array(3) [ 2, 2, 3 ]
是不是很奇怪,明明改变的是数组a1中的值,为什么数组a中的值也跟着改变了,这就不得不让人深思了。
那么这里,就需要引入基本数据类型和引用数据类型的概念了。
基本数据类型有哪些,number,undefined,null,string,boolean五类。
引用数据类型则有无序对象{a:1},数组[1,2,3],以及函数等。
当a1=a进行拷贝时,其实复制的是a的引用地址,而并非堆里面的值。此时,就是一个浅拷贝,数组a和数组a1共用同一条数据,无论改变其中哪一个数组的值,a和a1同时都会改变。
那么,如何实现对数据的深拷贝呢???
下面,同样让我们来看几个例子:
当只考虑要深拷贝的数据为对象时
var obj = {
a: '123',
b: 123,
c: {
test: 'aaa',
b: {
c: {},
d: 'hhh'
}
}
}
一维对象数据的深拷贝
var obj1 = {};
for(var x in obj){
obj1[x] = obj[x];
}
由运行结果可知,此时obj1已经完全将obj中的数据拷贝了过来。那么,现在让我们来验证一下,是否是深拷贝呢?
由运行结果可知,当改变对象obj中a的值时,obj1中a的值并没有发生改变。此时,即完成了对对象obj的深拷贝。但此时,仅是完成了对一层对象的深拷贝。
下面,让我们来看一下对多层对象的深拷贝,如下:
var obj1 = {};
// for(var x in obj){
// obj1[x] = obj[x];
// }
for (var x in obj) {
if (obj[x].constructor == Object) {
var res = {}
for (var k in obj[x]) {
if (obj[x][k].constructor == Object) {
var res1 = {}
for (var j in obj[x][k]) {
res1[j] = obj[x][k][j];
}
res[k] = res1;
} else {
res[k] = obj[x][k]
}
}
obj1[x] = res
} else {
obj1[x] = obj[x]
}
}
由运行结果可见,已实现了多层对象的深拷贝。
总结:
一层对象的对象的深拷贝
第一步:验证数据是否是对象?
第二步:
1.创建新的空对象res
2.遍历被拷贝的obj的对象,目的为了获取所有的key value
3.将key value 添加到res中
最后将res这个对象赋值给深拷贝的对象
将来res不论赋值给哪一个变量,该变量与obj之间都是深拷贝
当只考虑要深拷贝的数据为数组时:
var arr = [1, 2, 3, 4, [1, 2, 3, 4]]
var arr1;
if (Array.isArray(arr)) {
var res = [];
for (var i = 0; i < arr.length; i++) {
if (Array.isArray(arr[i])) {
var res1 = [];
for (var j = 0; j < arr[i].length; j++) {
res1.push(arr[i][j])
}
res.push(res1)
} else {
res.push(arr[i]);
}
}
arr1 = res;
} else {
arr1 = arr;
}
由运行结果可见,已实现了多层数组的深拷贝。
总结:
数组中深拷贝逻辑
第一步 验证数据是否为数组
第二步
1.新建一个空数组 res
2.遍历被拷贝的数组arr 目的为了获取arr中所有的值
3.将arr中所有元素添加到res中
4.将res赋值给需要深拷贝arr的变量arr1
递归深拷贝
递归:指的是在自己函数的内部调用自己
1.找规律
2.找出口(如果没有就是死循环)
var mh = {
a: [1, 3],
b: {
a: [1, 3],
c:{
a:2
}
}
}
function deepCopy(options) {
var res;
if (options instanceof Object) {
if (Array.isArray(options)) {
res = []
}
if (options.constructor === Object) {
res = {}
}
for (var k in options) {
res[k] = deepCopy(options[k])
}
} else {
res = options;
}
return res
}
var copyMh = deepCopy(mh);