【JS】深拷贝和浅拷贝

一、深浅拷贝的概念

1. 假设B复制了A,当修改B时,看A是否会发生变化,如果A也跟着变了,说明是浅拷贝,如果A没变,说明是深拷贝。

    即,深拷贝:所有属性都被拷贝,两者相互独立,互不影响;浅拷贝:并非所有属性都被拷贝,两者互相影响。

2. JS中的数据类型分为基本数据类型和引用数据类型。

(1)基本数据类型不存在深浅拷贝,两者相互独立,互不影响。

  当 var a = 1,var b = a 时,相当于在栈内存中新开辟了一个内存,如下所示:

(2)引用数据类型的浅拷贝,两者互相影响。

  当 var a = [0,1,2,3,4],var b = a 时,a 和 b 会指向同一个堆地址,所以当我们改变 a 时 b 也会改变,改变 b 时 a 也会改变,如下所示:

(3)引用数据类型的深拷贝,两者相互独立,互不影响。

  在深拷贝的情况下,我们会为 b 单独开辟一块堆内存,如下所示:

3. 深浅拷贝的概念只针对较为复杂的引用数据类型(对象类型)。

二、浅拷贝的实现

    浅拷贝直接用 “=” 赋值即可。

三、深拷贝的实现

1. 迭代递归法(只能实现object,array的深拷贝)

(1)for...in...法

  对对象进行迭代操作,对它的每个值进行递归深拷贝。

function isObject(o) {
    return (typeof o === 'object' || typeof o === 'function') && o !== null
}
// 迭代递归法:深拷贝对象与数组
function deepClone(obj) {
    if (!isObject(obj)) {
        throw new Error('obj 不是一个对象!')
    }
 
    let isArray = Array.isArray(obj)
    let cloneObj = isArray ? [] : {}
    for (let key in obj) {
        cloneObj[key] = isObject(obj[key]) ? deepClone(obj[key]) : obj[key]
    }
 
    return cloneObj
}

(2)Reflect 法 

function deepClone(obj) {
    if (!isObject(obj)) {
        throw new Error('obj 不是一个对象!')
    }
 
    let isArray = Array.isArray(obj)
    let cloneObj = isArray ? [...obj] : { ...obj }
    Reflect.ownKeys(cloneObj).forEach(key => {
        cloneObj[key] = isObject(obj[key]) ? deepClone(obj[key]) : obj[key]
    })
 
    return cloneObj
}

  拓展知识点:(1)ES6 Reflect (2)扩展运算符( ... )

2. 序列化反序列化法(只能实现object,array的深拷贝)

使用JSON对象的 parse 和 stringify 方法来实现深拷贝。通常应用于开发中,不用考虑除对象和数组以外的情况。

function deepClone(obj){
    let _obj = JSON.stringify(obj),
        objClone = JSON.parse(_obj);
    return objClone
}  

// 测试  
let a = [0,1,[2,3],4],
    b = deepClone(a);
b[0] = 1;
b[2][0] = 1;
console.log(a,b);
// a: [ 0, 1, [ 2, 3 ], 4 ] 
// b: [ 1, 1, [ 1, 3 ], 4 ]

3. lodash中深拷贝的实现

著名的 lodash 中的 cloneDeep 方法同样是使用 Reflect 方法实现的,只不过它支持的对象种类更多,具体的实现过程读者可以参考 lodash 的 baseClone 方法。lodash可以完成 object、array、date、regexp 的深拷贝,但 function 和 error 仍然不行。

参考:

【JS】深拷贝与浅拷贝的区别,实现深拷贝的几种方法

浅谈深拷贝和浅拷贝(js)

END

猜你喜欢

转载自blog.csdn.net/Dora_5537/article/details/90400552