拷贝顾名思义就是复制,但是它并不简单哦,拷贝分为深浅拷贝,那么啥是深拷贝啥是浅拷贝呢,让我们来举个栗子,浅拷贝就是当你拷贝别人的U盘里东西时,却没有新建文件存放在自己的电脑里,直接在里面修改,那么我们就更改了U盘里的内容,深拷贝就是在自己的电脑里新建了文件进行修改,而不会影响到原来的内容。好像栗子不是那么好吃,那我们来看看下面的解释吧!!!
深浅拷贝
1.深拷贝和浅拷贝只针对像Object, Array这样的引用类型数据。
2.浅拷贝是对对象引用地址进行拷贝,并没有开辟新的栈,也就是拷贝后的结果是两个对象指向同一个引用地址,修改其中一个对象的属性,则另一个对象的属性也会改变。
3.深拷贝则是开启一个新的栈,两个对象对应两个不同的引用地址,修改一个对象的属性,不会改变另一个对象的属性。
浅拷贝
直接上栗子吧
var myInfo = {name:'liu',sex:'女'};
var newInfo = myInfo;
console.log(myInfo); //{name:'liu',sex:'女'}
newInfo.sex = '小仙女';
console.log(myInfo); //{name:'liu',sex:'小仙女'}
可以看到newInfo复制了myInfo里的内容,本应他们之间没有联系的,可是为什么当newInfo更改时同时也影响了myInfo?那是因为这只是浅拷贝,newInfo的地址并没有更改,指向同一个栈。
深拷贝
让我们先对比一下下面的两个栗子吧!
var array = [{a:1,b:2},{a:3,b:4}];
var newArray = Object.assign([],array);
newArray.length = 1;
console.log(newArray);
console.log(array);
newArray[0].a = 123;
console.log(array[0]);
function deepClone(obj){
if(!obj&& typeof obj!== 'object'){
return;
}
var newObj= obj.constructor === Array ? [] : {};
for(var key in obj){
if(obj[key]){
if(obj[key] && typeof obj[key] === 'object'){
newObj[key] = obj[key].constructor === Array ? [] : {};
//递归
newObj[key] = deepClone(obj[key]);
}else{
newObj[key] = obj[key];
}
}
}
return newObj;
}
var array = [{a:1,b:2},{a:3,b:4}];
var newArray = deepClone(array);
console.log(array[0]);
newArray[0].a = 123;
console.log(array[0]);
大家思考一下,这两个栗子会是一样吗?
来公布一下正确答案:
先看第一个栗子
[{a:1,b:2},{a:3,b:4}]
{a: 123, b: 2}
(问号脸)我明明没有更改myInfo的数据啊,这么回事?
因为Object.assign并不是深拷贝,是披着深拷贝外衣的浅拷贝。最多也是Object.assign会拷贝第一层的值,对于第一层的值都是深拷贝,而到第二层的时候就是复制引用。类似的情况还有,slice方法和concat方法等。
来看看第二个
{a:1,b:2}
{a:1,b:2}
两个结果都是一样的,为什么呢?
因为这才是深拷贝啊,newInfo开启了一个新的栈,虽然内容相同,可是他们已经在不同地点了,互不影响。这里我们采用了封装和递归,如果对象属性的值是引用类型(Array,Object),那么对该属性进行深拷贝,直到遍历到属性的值是基本类型为止。好像有点复杂诶,没事,我们还有个简单粗暴的方法!!!
var newArray = JSON.parse(JSON.stringify(array));
console.log(array[0])//{a:1,b:2}
newArray[0].a = 123
console.log(array[0])//{a:1,b:2}
利用JSON解析函数把对象转成字符串,再把字符串转成对象!四不四很简单呀!?
这就是我对于深浅拷贝的了解了,如果有更好的见解要告诉我哦!?