js对象的浅拷贝和深拷贝方法整理,深拷贝的原生实现

蛰伏已久 蛰伏已久 2019-10-23

对象的浅拷贝

1 通过对象展开符... 实现浅拷贝

let obj = {
    a:123,
    b:[1,2,3,4],
    c:{
        c1:'a',
        c2:'b',
        c3:[1,2,3,{c31:2}]
    }
}

let copyObj = {...obj}

copyObj.a = '456'
copyObj.c.c1 = 'aaaaa'
console.log(obj.a)   //123  没变,还保持原样
console.log(obj.c.c1 ) //aaaaa  变了,由于obj.c是对象,所以跟着copyObj的修改变了,说明是浅拷贝


2 通过Object.assign实现浅拷贝

注意:Object.assign的第一个参数是一个空对象,而不能使obj,否则就不是浅拷贝了,是直接赋值了,没有实现拷贝的目的

let obj = {
    a:123,
    b:[1,2,3,4],
    c:{
        c1:'a',
        c2:'b',
        c3:[1,2,3,{c31:2}]
    }
}

let copyObj = Object.assign({},obj)

对象的深拷贝

1 通过JSON.parse(JSON.stringify)

这种方式有个问题,就是当值为 undefined、函数或Symbol的时候,不会被拷贝,所以使用要注意

let obj = {
    a:null,
    b:undefined,
    c:function () {
        console.log("我是函数")
    },
    d:Symbol()
}

console.log(JSON.parse(JSON.stringify(obj))) // {a:null}  其他数据丢失了

2.通过递归实现对象深度拷贝

实现比较简单,有几个点需要注意,第一就是对传入的参数进行判断,参数必须为对象;第二就是对象中可能包含数组,要考虑数组的深度拷贝

let obj = {
    a:123,
    b:[1,2,3,4],
    c:{
        c1:'a',
        c2:'b',
        c3:[1,2,3,{c31:2}]
    }
}

function deepClone(obj) {

    //先写个判断是否为对象的函数 
    function isObject(obj) {
        if(typeof obj ==='object' && obj !== null){
            return true
        }else{
            return false
        }
    }

    //对传入参数进行判断
    if(!isObject(obj)){
        console.log("传入的参数必须为对象")
        return
    }

    //数组就返回数组,对象就返回对象
    let result = Array.isArray(obj)?[]:{}

    //for in可以遍历数组和对象
    for(let key in obj){
        if(isObject(obj[key])){
            //是对象就递归
            result[key] = deepClone(obj[key])
        }else{
            //不是对象就直接复制
            result[key] = obj[key]
        }
    }

    return result
}


let copyObj = deepClone(obj)

copyObj.a = '456'
copyObj.c.c1 = 'aaaaa'

console.log(obj.a)   //123 保持了原来的值
console.log(obj.c.c1 ) //a 保持了原来的值,说明是深度拷贝

console.log(copyObj)
console.log(obj)

这个方法不仅可以进行对象的深度拷贝,还能进行数组的深度拷贝

分享到

点赞(0)