深拷贝和浅拷贝的区别

113 阅读1分钟
  1. 浅拷贝 浅拷贝出现的前提:引用类型的数据(对象和数组)
  • 浅拷贝当把obj1赋值给obj2的时候,再去通过obj2修改里面的属性obj1会跟着一起变。
const obj1 = {
    a= 1
}
const obj2 = obj1
obj2.a = 2
console.log(obj1.a, obj2.a) //2 2
  1. 深拷贝
  • 对于基本数据类型的赋值可以理解为深拷贝。将a的值赋给b相当于重新开辟了内存空间来存放b,修改b的值将不会影响到a的值。
const a = 1
const b = a
b = 2
console.log(a, b) //1 2
  • 如果想要对引用类型进行深拷贝使用JSON.parse(JSON.stringify(obj1))来实现。但是这种方法会有缺点:数据类型为function或者数据值为undefined时无法复制。
const obj1 = {
    a: 1,
    b: undefined,
    c: [1,2,3],
    d: () => {}
}
const obj2 = JSON.parse(JSON.stringify(obj1))
obj2.a = 2
obj2.c[0] = 11
console.log(obj1, obj2) //会发现obj1不会发生改变,obj2中缺少b d属性
  • 还可以使用Object.assign({}, obj1),它的缺点是:只能拷贝一级属性二级以上的属性(引用类型)就是浅拷贝。
const obj1 = {
    a: 1,
    b: undefined,
    c: [1,2,3],
    d: () => {}
}
const obj2 = Object.assign({}, obj1)
obj2.a = 2
obj2.c[0] = 11
console.log(obj1, obj2) //会发现obj1.c会跟随obj2.c一起改变
  • 扩展运算符(...),它的缺点也是:只能拷贝一级属性二级以上的属性(引用类型)就是浅拷贝。
const obj1 = {
    a: 1,
    b: undefined,
    c: [1,2,3],
    d: () => {}
}
const obj2 = {...obj1}
obj2.a = 2
obj2.c[0] = 11
console.log(obj1, obj2) //会发现obj1.c会跟随obj2.c一起改变
  • 递归
function CloneDeep (obj, map = New map){
    if(typeOf obj !== 'object') {
        return obj
    } else {
        const obj_ = arr.isArry(obj) ? [] : {}
        if(!map.get(obj)) {
            map.set(obj, obj_)
            for(let key in obj) {
                obj_ = CloneDeep(obj[key], map)
            }
            return obj_
        } else {
            return map.get(obj)
        }
    }
}
  • 补充:对于数组中的slice, concat也可以进行深拷贝,确定同样是:只能拷贝一级属性二级以上的属性(引用类型)就是浅拷贝。