对象的深浅拷贝
- 基本类型&引用类型
- 深拷贝&浅拷贝
- 深拷贝的实现方法
- 方法一:递归&for循环
- 方法二:利用JSON.parse()和JSON.stringify()(更简单)
- 方法三:Object.assign()实现
基本类型&引用类型
基本类型
- JS的七大数据类型中除了object都是基本类型。(null、undefined、number、string、boolean、symbol)
- 基本类型的存储方式是以固定大小的方式存储在栈内存中。
- 在进行a=b的操作时,会创造b的一个副本,把这个副本赋值给a;
let a=1;
let b=a;
document.write(a==b); //=>ture
b=2;
document.write(a==b); //=>false
document.write(a,b); //=>(1,2)
引用类型
- object、Array、function属于引用类型 (RegExp属于function)。
- 对象是保存在堆内存中的,而栈内存存储的是对象的变量标识符以及对象在堆内存中的存储地址。
- 在进行a=b的操作时,与基本类型类似,会创造b的一个副本,把这个副本赋值给a,但是!!此时b只是个指针,最后a和b指向同一个对象;
let a=[1,2,3];
let b=a;
document.write(a==b); //=>ture
b[0]=2;
document.write(a==b); //=>ture
document.write(a,b); //=>[2,2,3],[2,2,3]
深拷贝&浅拷贝
- 浅拷贝发生的原因是仅复制了引用,彼此之间的操作会互相影响,并没有在堆中重新分配内存。
- 深度拷贝需要实现在堆中重新分配内存,不同的地址,相同的值,互不影响。
- 但是要注意number;
需要重新写一篇关于number的
深拷贝的实现方法
方法一:递归&for循环
- 对属性中所有引用类型的值进行遍历并递归,直到是基本类型值为止。
- 简单示例:对于简单的对象类型
let arr1=[1,2,3];
let arr2=[];
for(let i of arr1)
arr2.push(i);
console.log(arr1,arr2);
arr2[0]=2;
console.log(arr1,arr2);
var deepCopy = function(obj){
if(!obj && typeof obj !== 'object'){
throw new Error('error args');
}
let res=Array.isArray(obj) ? []:{};
for(let key in obj){
if(obj.hasOwnProperty(key)){
if (obj[key] && typeof obj[key] === 'object')
res[key]=deepCopy(obj[key]);
else
res[key]=obj[key];
}
}
return res;
}
方法二:利用JSON.parse()和JSON.stringify()(更简单)
- JSON.parse():把JSON字符串反序列化为一个js对象
- JSON.stringify():把一个js对象序列化为一个JSON字符串
- 缺点:当有属性是undefined或null的时候会被移除掉。
- 使用示例:
let obj1 = {
name: '小吴',
gender: 'female',
habit :['发呆','睡觉'],
age: undefined
};
let obj2=JSON.parse(JSON.stringify(obj1));
obj2.habit.push('吃饭');
console.log(obj1,obj2);
方法三:Object.assign()实现
- 只能实现简单的对象深拷贝;如果对象中存在多级属性的话,是无法实现的。
- 语法:
returntarget=Object.assign(target,…source);
具体内容请自行查找,这里的target和returntarget是相等的,即引用的对象是同一个。
- 使用示例:
const source1 = { a:[1,2,3],b: 4, c: 5 };
const source2 = { d:6 };
const target = Object.assign({},source1,source2);
console.log(target,source1);
target['a'][0]=2;target['b']=10;
console.log(target,source1);