对象深拷贝是什么?
我们在js中对“字符串”、“数字”、“布尔值”进行拷贝一般只要“=”号就行了
但是在对象和数组中使用“=”,那只是进行“浅拷贝”(指针指向同一个堆内存地址)。
浅拷贝示例
将a赋值给b,a和b这两个栈内存变量的指针指向同一个堆内存地址
vara={name:"铅笔",color:"red"};
varb=a;
b.name="篮球";`在这里插入代码片`
console.log(a,b)
如上 b的值改变,会影响a的值,这在大多数情况下不是我们想要的。
深拷贝就是对目标的完全拷贝,不像浅拷贝那样只是复制了一层引用,就连值也都复制了。
只要进行了深拷贝,就老死不相往来,谁也不会影响谁。
对象如何进行深拷贝?
目前只有 两种方法:
一个是递归,一个是JSON.stringify/JSON.parse方法
JSON.stringify/JSON.parse方法
vara={
name:"铅笔",
color:"red"
};
varb=JSON.parse(JSON.stringfiy(a));
b.name="篮球";
console.log(a,b)
如上成功进行深拷贝,但是这个方法不是所有情况下都适用的
vara={
name:"铅笔",
color:"red",
getName:function(){
console.log(this.name);
}
};
varb=JSON.parse(JSON.stringify(a));
b.name="篮球";
console.log(a,b)
b.getName()
undefined、function、symbol 会在转换过程中被忽略。。。,所以当对象里有这三个值的时候就不能使用这个方法
递归方法
functiondeepClone(obj1){
varobj2=obj1.constructor===Array?[]:{};
for(keyinobj1){
//如果没这个属性就结束本次循环
if(!obj1.hasOwnProperty(key)){
continue;
}
//是对象就递归一下,不然就直接赋值
if(typeof obj1[key]==='Object'){
obj2[key]=deepClone(obj1[key]);
}else{
obj2[key]=obj1[key];
}
}
returnobj2;
}
vara={
name:'小明',
age:18,
say:function(){
console.log('我叫'+this.name)
}
};
varb=deepClone(a);
b.name='小环';
console.log(a,b);
b.say();
首层深拷贝
对目标对象的第一层进行深拷贝,然后子层的是浅拷贝,我称它为“首层深拷贝”
为什么叫首层深拷贝?
举个栗子:
vararr=['一个字符串',{name:'小环',age:21}];
b=arr.slice(0);
b[0]=123123;
b[1].name='小新';
b[1].age=6;
console.log(arr,b);
console.log('是否指向同一内存地址');
console.log(arr[1]===b[1]);
1、对”b[0]“重新赋值为“123123”,结果也如我们想象的那样互不影响。
2、但是对”b[1]“进行更改时,arr[1]也发生了相同更改。显然它们指向同一个对象
代码 arr[1] === b[1] 为 true,说明它们确实指向同一地址
所以首层是深拷贝,第二层后的目标都只是复制了一个引用是浅拷贝。
数组
slice方法
vararr=[1,2];
b=arr.slice(0);
b.push('aaa');
console.log(arr,b);
concat方法
vararr=[1,2];
b=arr.concat();
b.push('aaa');
console.log(arr,b);
三点运算符
vararr=[1,2];
b=[...arr];
b.push(99);
console.log(arr,b);
对象
Object.asign()方法
vara={
name:"铅笔",
color:"red",
getName:function(){
console.log(this.name);
}
};
varb=Object.assign({},a);
b.name="篮球";
console.log(a,b);
b.getName();
总结:
- 赋值运算符”=“拷贝对象实现的是浅拷贝,只拷贝对象的引用值;
- JavaScript 中数组和对象自带的拷贝方法都是“首层深拷贝”;
- JSON.stringify/JSON.parse 实现深拷贝,对目标对象有要求(非undefined,function、symbol);
- 若想真正意义上的深拷贝,请递归若想真正意义上的深拷贝,请递归