谈到深拷贝和浅拷贝,首先要知道javascript的数据类型和存储方式。
JS数据类型:可分为简单数据类型(基本数据类型)和复杂数据类型(引用数据类型):
简单数据类型:String、Number、Boolean、undefined和null
复杂数据类型:通过new创建的对象、系统对象、自定义对象。如:Object、Array、Date等
简单数据类型和复杂数据类型的存储方式也是不一样的,这时就要引入堆和栈的概念。堆和栈不做深入讲解。总之,
简单数据类型存储在栈中;
复杂数据类型则存储在堆里,在栈中会存储一个十六进制的地址指向堆中的数据。
/*堆和栈*/
// 简单数据类型
var a = 1;
var b = a;
a = 3;
console.log(b)// b=1
// 复杂数据类型
var obj1 = {
b: 1,
c: {
c1: 123
},
d: 3
}
var obj2 = obj1;
console.log(obj2.b)//1
obj1.b = 2;
console.log(obj2.b)// 2
如上所示,简单数据类型就不说了。复杂数据类型在把obj1赋值给obj2的时候obj2的b的值是1,然后再修改obj1的b的值后,发现obj2的b的值也随之修改了。
因为obj2和obj1存储的是指向堆中的一个十六进制地址,obj1和obj2指向堆中的数据是同一个。所以通过obj1修改了堆中的值,响应的obj2取到堆中的值也随之变化了。这个就是一个浅拷贝的过程,浅拷贝只拷贝了复杂数据的地址。
反之,深拷贝则拷贝整个复杂数据的值。那如何实现深拷贝?对象可以使用for…in进行遍历,我们可以遍历对象,一级一级地进行拷贝。
总体思路就是,使用for…in进行对象的遍历,当碰到复杂数据类型时,再进行一次for…in遍历,一级一级地拷贝。这是就会使用到递归的方式。
var obj = { //被拷贝的对象
name: 'xm',
age: '22',
sex: '男',
home: {
city: '浙江',
},
hobby: {
hobby1: ['chi', 'he', 'play'],
hobby2: {
ceshi: [123, 456, 789],
xm: 'nb'
}
}
}
var obj1={};//想要拷贝到这个对象
function shenkaobei(obj, obj1) {
for (var k in obj) { //for...in遍历对象
if (obj[k] === 'object') {//一级一级进去,如果是复杂数据类型,调用shenkaobei这个函数
shenkaobei(obj[k], obj1[k]);
} else {
obj1[k] = obj[k];
}
}
return obj1;
}
obj1 = shenkaobei(obj, obj1);
obj.hobby = {
ceshi: 6666
}
console.log(obj)
console.log(obj1)