深拷贝和浅拷贝最根本的区别在于是否真正获取一个对象的复制实体,而不是引用。
深拷贝与浅拷贝只针对于引用数据类型来说:
浅拷贝(shallowCopy)只是复制了一层对象的属性,不包含子对象的属性;子对象属性若变化时,复制的对象的子对象属性也跟着变化,子对象属性仍然指向同一地址
深拷贝(deepCopy)是复制了所有层级的属性,所有子对象属性都是另外开辟了一块新的栈内存,指向不同的地址;
实现浅拷贝的方法
let a={a:1,b:{2}}
let b=Object.assgin({},a)
实现深拷贝的方法:
1.JSON转换:
let obj={a:1,b:2}
let newObj=JSON.parse(JSON.stringfy(obj))
缺点:
1.如果对象里有函数,函数无法被拷贝下来
2.无法拷贝copyObj对象原型链上的属性和方法
2.递归方法:
const source = {
field1: 1,
field2: undefined,
field3: {
child: 'child'
},
field4: [2, 4, 8]
};
source.source = source;
//上面的对象存在循环引用的情况,即对象的属性间接或直接的引用了自身的情况:
//克隆source会出现因为递归方法会出现内存溢出的问题,以下是解决方法:
function deepCopy( source,map=new Map() ) {
if (!isObject(source)) return source; //如果不是对象的话直接返回
let target = Array.isArray( source ) ? [] : {} //数组兼容
//为了解决内存溢出的问题:将当前对象作为键,克隆对象作为值保存到map对象中
if(map.get(source)){ //检查map对象中是否含有当前对象
return source; //如果有说明当前对象已经被克隆过则返回当前对象
}
map.set(source,target)//没有则写入map对象中
for ( var k in source ) {
if (source.hasOwnProperty(k)) {
if ( typeof source[ k ] === 'object' ) {
//若对象中的这项值还为对象的话,则利用递归的方法将其复制
target[ k ] = deepCopy( source[ k ] )
} else {
target[ k ] = source[ k ]
}
}
}
return target
}
function isObject(obj) {
return typeof obj === 'object' && obj !== null
}
缺点:
1.不支持正则,函数的深拷贝
2.层级嵌套太多会内存溢出(上面已解决!)