浅拷贝只是拷贝一层,浅拷贝一个对象的属性值如果是一个引用数据类型,那只会拷贝这个引用数据类型的指针地址,此时如果对拷贝后的此引用数据类型属性值进行修改的话,也会同时修改对应原始对象该引用属性类型属性值。
举例如下:
下面的例子对obj进行浅拷贝,由于该对象b属性的属性值是引用数据类型,该属性值对应了一块内存地址,浅拷贝后只是拷贝了其地址,所以newObj,b属性值依旧指向该地址。对newObj.b.c进行修改,还会同时修改其原始对象obj,所以newObj.b.c === obj.b.c结果为true
let obj = {
a: [1, 2, 3],
b: {
c: 2,
d: 3
}
}
let newObj = {...obj}
newObj.b.c = 99999
console.log(newObj.b.c === obj.b.c)//true
深拷贝的目的是深拷贝后原始对象和拷贝后的对象互不影响,显然浅拷贝不符和要求,我们希望对引用数据类型地址所指的内存空间中的属性和属性值进行拷贝,拷贝到一个新的地址上,而不是简单复制其地址,造成原始对象后拷贝后的对象的互相影响
下面是一个简单的实现深拷贝的例子,虽然有许多地方没有考虑到,不够完善,但是可以应付大多数使用场景
function deepClone(obj){
function isObject(o){
return (typeof o === 'object'|| typeof o === 'function')&&o!=null
}
if(!isObject(obj)){
console.log('非对象')
return
}
let isArray = Array.isArray(obj)
let newObj = isArray?[...obj] : {...obj}
Object.keys(newObj).forEach(k=>{
newObj[k]=isObject(obj[k])?deepClone(obj[k]):obj[k]
})
return newObj
}
let obj = {
a: [1, 2, 3],
b: {
c: 2,
d: 3
}
}
let newObj = deepClone(obj)
console.log(newObj, obj===newObj)//{a: [1, 2, 3], b: {c: 2,d: 3}} false
console.log(obj.a===newObj.a)//false