手写实现一个深拷贝

部分一:

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

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

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

解构赋值是不是深拷贝?

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

深拷贝方法:

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等其余方式进行替换。