手写实现一个深拷贝

部分一:

简介:手写实现一个深拷贝属于数据结构的知识点,数据类型包含基本类型和引用类型,基本类型存储在栈中;引用数据类型存储在堆中;基本数据类型没有浅拷贝和深拷贝的区分,浅拷贝和深拷贝的问题存在于引用数据类型中。

浅拷贝:只拷贝了内存空间的地址;

深拷贝:开辟新的内存空间,两块空间相互之间不影响;

解构赋值是不是深拷贝?

不是,一维数组或对象是深拷贝,多维则是浅拷贝;

深拷贝方法:

JSON.parse(JSON.stringfy(obj))

手写深拷贝方法:

/*手写深拷贝思路:
1.判断拷贝的对象是数组还是对象
2.遍历属性
  是否还有数组或对象 =>递归
  基本数据类型 => 赋值*/

const deepCopy = (obj) =>{
    //1.判断拷贝的对象是数组还是对象
    const newObj = obj.constructor === Array ? [] : {}
    //2.遍历属性
    for(let key in obj){
        if(obj.hasOwnProperty(key)){
            //是否还有数组或对象
            if(obj[key] && typeof obj[key] === 'object'){
                //递归
                newObj[key] = deepCopy(obj[key])
            }else{
                //基本数据类型
                newObj[key] = obj[key];
            }
        }
    }
    return newObj;
}

const object1 = {
    a:1,
    b:'深拷贝',
    arr:[1,2,3],
    boj2:{
        aa:1,
        bb:'深拷贝'
    }
}

const x = deepCopy(object1);
x.c = 100;
console.log(x)
console.log(object1)

//hasOwnProperty 会返回一个布尔值,判断对象中是否存在该属性

部分二:

上面的obj.hasOwnProperty(key)存在一些问题,由于javascript没有将hasOwnProperty作为一个敏感词,外部可以自己定义它,就有可能覆盖该属性,从而失去它原本的功能,列如:

function test(){
    const ob = {a:1}
    ob.hasOwnProperty = 0;
    console.log(ob.hasOwnProperty('a'))
}
test()

function test(){
    const ob = {a:1}
    ob.hasOwnProperty = () => false;
    console.log(ob.hasOwnProperty('a'))
}
test()

解决方法:

使用Object.prototype.hasOwnProperty.call(obj, key)

改进深拷贝

/*手写深拷贝思路:
1.判断拷贝的对象是数组还是对象
2.遍历属性
  是否还有数组或对象 =>递归
  基本数据类型 => 赋值*/
 
const deepCopy = (obj) =>{
    //1.判断拷贝的对象是数组还是对象
    const newObj = obj.constructor === Array ? [] : {}
    //2.遍历属性
    for(let key in obj){
        if(Object.prototype.hasOwnProperty.call(obj, key)){
            //是否还有数组或对象
            if(obj[key] && typeof obj[key] === 'object'){
                //递归
                newObj[key] = deepCopy(obj[key])
            }else{
                //基本数据类型
                newObj[key] = obj[key];
            }
        }
    }
    return newObj;
}
 
const object1 = {
    a:1,
    b:'深拷贝',
    arr:[1,2,3],
    boj2:{
        aa:1,
        bb:'深拷贝'
    }
}
 
const x = deepCopy(object1);
x.c = 100;
console.log(x)
console.log(object1)
 
//hasOwnProperty 会返回一个布尔值,判断对象中是否存在该属性
//Object.prototype.hasOwnProperty.call(obj, key)

// 不要轻易使用Object.prototype的方法:
// 例如 hasOwnProperty, propertyIsEnumerable 和 isPrototypeOf 方法:
// 这些方法可能被对象自身的同名属性覆盖或者对象是个null对象。
// 如果一定要使用,可以使用Object.prototype.hasOwnProperty.call()、Object.keys().includes()、in等其余方式进行替换,最大程度的保证程序不出bug!!!

总结:

不要轻易使用Object.prototype的方法,例如 hasOwnProperty, propertyIsEnumerable 和 isPrototypeOf 方法,这些方法可能被对象自身的同名属性覆盖或者对象是个null对象。

如果一定要使用,可以使用Object.prototype.hasOwnProperty.call()、Object.keys().includes()、in等其余方式进行替换。

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yue200403

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值