几个例子理解浅拷贝和深拷贝
一、内存的堆栈
- 基本类型
存放在栈内存中的简单数据段,数据大小确定,内存空间大小可以分配,当它赋给另一个变量的时候,另一个变量发生改变,原数据不会发生改变:
var a = 5;
var b = a;
b += 1;
console.log(b) //6
console.log(a) //5
5种基本数据类型有Undefined、Null、Boolean、Number 和 String,它们是直接按值存放的,所以可以直接访问。
- 引用类型
存放在堆内存中的对象,变量实际保存的是一个指针,这个指针指向另一个位置。每个空间大小不一样,要根据情况进行特定的分配。当我们需要访问引用类型(如对象,数组,函数等)的值时,首先从栈中获得该对象的地址指针,然后再从堆内存中取得所需的数据。
var a = { userName : 'undefined' };
var b = a;
b.userName = 'xiaoming';
console.log(a); //{userName: "xiaoming"}
console.log(b); //{userName: "xiaoming"}
上面的例子把a的值赋值给b,当b的值发生改变的时候,a的值也会跟随改变,像上面的图解一样,a和b都是指向同一个地址。如果要让b得到一个独立的地址呢?这就涉及到拷贝了。
二、Object.assign
浅拷贝是复制浅层的引用类型,比如复制a = { userName : 'undefined' }这样的对象就是属于浅拷贝,它只有一层,像复制b = { info : { userName : 'undefined' } }这样有嵌套的对象,多层的引用类型,就需要用到深拷贝了。
- Object.assign()方法可以得到一份浅拷贝的引用类型
var a = { userName : 'undefined' };
var b = Object.assign({} , a);
b.userName = 'xiaoming';
console.log(a); //{userName: "undefined"}
console.log(b); //{userName: "xiaoming"}
这样,我们就能得到一份浅拷贝内容了,即使是b发生改变,也不会影响到a,它们完全是两个独立的个体,但是此方法不适用深拷贝。
三、展开运算符
- 利用展开运算符方法也可以得到一份浅拷贝的引用类型:
var a = { userName : 'undefined' };
var b = {...a};
b.userName = 'xiaoming';
console.log(a); //{userName: "undefined"}
console.log(b); //{userName: "xiaoming"}
这样,我们也能得到一份浅拷贝内容。
四、JSON.parse()&JSON.stringify()
- 利用JSON下面的parse()方法和stringify()方法可以得到一份深拷贝内容,stringify()方法可以把对象转变成json格式的字符串,再通过parse()方法进行转译成对象来获得一份拷贝的对象(当然浅拷贝也是适用的):
var a = { info:{userName : 'undefined'}};
var b = JSON.parse(JSON.stringify(a));
b.info.userName = 'xiaoming';
console.log(a); // { info:{userName : 'undefined'}};
console.log(b); // { info:{userName : 'xiaoming'}};
五、for...in&递归(推荐)
- 这种方法适用于任何引用类型,原理是使用for..in循环,配合递归函数实现深层拷贝 :
var a = { info:{userName : 'undefined'}};
var b = copy(a);
b.info.userName = 'xiaoming'
function copy(obj){
var result = {};
for(var attr in obj){
if( typeof obj[attr] === 'object' ){
result[attr] = copy(obj[attr]);
}
else{
result[attr] = obj[attr];
}
}
return result;
}
console.log(a); // { info:{userName : 'undefined'}};
console.log(b); //{userName: "xiaoming"}
这样,就可以得到一份深拷贝内容了,其原理就是层层拷贝,利用递归的原理,直到最底层不是对象为止,好啦,本次分享就到这里了,如果有什么不正确的地方,请各位不吝赐教,谢谢~