深拷贝的常用写法

1. 使用JSON.parse来实现

cloneObj = JSON.parse(JSON.stringify(obj))

为什么它可以实现深拷贝

  1. 序列化和反序列化

    • JSON.stringify(obj):将对象转换为 JSON 字符串。这个过程会递归遍历对象的所有属性,并将其转换为字符串形式。
    • JSON.parse(string):将 JSON 字符串解析回一个新对象。这个过程会创建一个新的对象,并填充从字符串中解析出来的属性。
  2. 断开引用关系

    • 由于经过了序列化(stringify)和反序列化(parse),原对象和新对象之间没有任何引用关系,因此修改新对象不会影响原对象,反之亦然。

局限性

  • 无法处理函数 :函数在序列化时会被忽略,因此新对象中不会包含任何函数属性。
    const obj = { a: 1, b: function() {} };
    const clone = JSON.parse(JSON.stringify(obj));
    console.log(clone.b); // undefined

  • 无法处理复杂的数据类型:例如 DateRegExpMapSet 等复杂数据类型,在序列化时会被转换为普通对象或丢失信息。
    const obj = { date: new Date(), regExp: /abc/ };
    const clone = JSON.parse(JSON.stringify(obj));
    console.log(clone.date instanceof Date); // false
    console.log(clone.regExp instanceof RegExp); // false

  • Symbol 类型Symbol 类型的键在序列化时会被忽略。
    const obj = { [Symbol('a')]: 'value' };
    const clone = JSON.parse(JSON.stringify(obj));
    console.log(clone); // {}
    
     

 2.手动递归拷贝

为了克服上述局限性,可以使用更健壮的深拷贝方法,例如:

手动递归拷贝:如你之前提供的代码片段所示,通过递归遍历对象并复制每个属性。

function deepClone(obj){
    let cloneObj;
    // 判断当输入的数据是简单数据类型时,直接复制
    if(obj && typeof obj !== 'object'){
        cloneObj = obj;
    }
    // 当输入的数据是对象或者数组时
    else if(obj && typeof obj === 'object'){
        // 检测输入的数据是数组还是对象
        cloneObj = Array.isArray(obj) ? [] : {};

        // 变量数据对象
        for(let key in obj){
            // 判断对象是否存在key属性
           //判断是否存在自定义属性 hasownProperty
            if(obj.hasOwnProperty(key)){
                if(obj[key] && typeof obj[key] === 'object'){
                    // 若当前元素类型为对象时,递归调用
                    cloneObj[key] = deepClone(obj[key]);
                }
                // 若当前元素类型为基本数据类型
                else{
                    cloneObj[key] = obj[key];
                }
            }
        }
    }
    return cloneObj;
}

 可以进一步改进:

使用 Object.keys() 或 Object.entries():这些方法只会遍历对象自身的可枚举属性,从而避免了显式检查 hasOwnProperty

if (obj && typeof obj == 'object') {
    const cloneObj = Array.isArray(obj) ? [] : {};
    
    Object.keys(obj).forEach(key => {
        if (typeof obj[key] === 'object' && obj[key] !== null) {
            cloneObj[key] = deepClone(obj[key]);
        } else {
            cloneObj[key] = obj[key];
        }
    });

    return cloneObj;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值