基本数据类型:number,string ,boolean,null,undefined,bigInt,symbol
复杂(引用、Object类型)数据类型:object,arry,date,function,regexp
基本数据类型存储在栈中,复杂数据类型存储在堆中,在栈中只保留复杂数据类型的属性和引用地址

浅拷贝:复杂数据类型的存在赋值关系的两个变量指向同一个引用地址
深拷贝:旧对象指向原来的引用地址,新对象在堆中创建一个新的空间,指向新的引用地址
浅拷贝原理:
const oldObj={
name:'哈默',
age:20,
colors:['orange','green','blue'],
friend:{
name:'小夏'
},
}
const newObj=oldObj;
newObj.name='小野';
console.log('oldObj',oldObj);
console.log('newObj',newObj);
解析:oldObj.name和newObj.name的值是一样的,因为是浅拷贝,我们改变了对象的一个值,另一个对象对应的值也会跟着改变;
当我们不希望出现同步改变的时候,就会用到深拷贝;
即newObj的值发生改变时,oldObj的值不会改变
const oldObj={
name:'哈默',
age:20,
colors:['orange','green','blue'],
friend:{
name:'小夏'
},
}
function deepClone(obj){
if( typeof obj !=='object'||obj == null){
return obj;}
let result;
if(obj instanceof Array){
result= [];
}else{
result={};
};
for(let key in obj){
result[key]=obj[key]
};
return result;
}
const newObj=deepClone(oldObj);
newObj.name='小野';
console.log('oldObj',oldObj);
console.log('newObj',newObj);
但是这种方式的深拷贝,只拷贝了一层,它不会去处理嵌套的对象,如oldObj.friend.name的值
所以我们不能直接赋值,应该在函数里面应该递归的调用函数本身;完成嵌套对象的值的深拷贝
for(let key in obj){
result[key]=deepClone(obj[key])
}
还有一个优化点是,应该只拷贝原来对象上自身的属性,原来对象原型上的属性不应该拷贝
for(let key in obj){
if(obj.hasOwnProperty(key)){
result[key]=deepClone(obj[key])
}
}
遗留点: 没有讲循环引用问题
循环引用解决思路:添加一个参数cache,里面存储处理过的参数,当遇到循环引用时,将cache中存储的信息返回即可
1、JSON.parse(JSON.stringify())
2、借助第三方库lodash实现深拷贝
var shallowObj2 = { ...obj1 }
2、Object.assign()
参考: