JS深拷贝与浅拷贝

浅拷贝

地址指向

    var obj1 = {
        'name':'zhang',
        'age':1,
        'lang':[1,[2,3],[4,5]]
    }
    var obj2 = obj1
    obj2.name = 'new'
    obj2.lang[1] = [6,6]
    console.log(obj1)
    console.log(obj2)

JS深拷贝与浅拷贝_第1张图片
object为引用数据类型
指向为同一个地址,obj1与obj2指向同一个地址
obj1改变 obj2也会进行改变

浅拷贝

方法1 通过for in循环遍历
    var obj1 = {
        'name': 'zhang',
        'age': 1,
        'lang': [1, [2, 3], [4, 5]]
    }

    //浅拷贝
    //第一层数据不会使原数据改变
    //原数据中包含的子对象改变会使原数据改变
    function shallowCopy(src) {
        var dst = {}
        for (var key in src) {
            if (src.hasOwnProperty(key)) {
                dst[key] = src[key]
            }
        }
        return dst
    }
    var obj3 = shallowCopy(obj1)
    obj3.name = 'obj3name'
    obj3.lang[0] = [6, 6]
    console.log(obj3)

JS深拷贝与浅拷贝_第2张图片name值改变,但数组值未发生改变

方法2 Object.assign()

Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。但是 Object.assign()进行的是浅拷贝,拷贝的是对象的属性的引用,而不是对象本身

    //当Object只有一层时,为深拷贝
    var obj = {
        a:'assign拷贝'
    }
    var obj2 = Object.assign({},obj)
    obj2.a = '拷贝新数据'
    console.log(obj)
    console.log(obj2)

JS深拷贝与浅拷贝_第3张图片

    //Object包含子对象,为浅拷贝
    var obj = {
        a: {
            name: 'assign浅拷贝',
            title: '数据'
        },
        b:'old'
    }
    var obj2 = Object.assign({}, obj)
    obj2.a.name = '是否为深拷贝?'
    obj2.b = 'new'
    console.log(obj)
    console.log(obj2)

JS深拷贝与浅拷贝_第4张图片

方法2 Array.prototype.concat()
    var arr = [1,2,{name:'array拷贝'}]
    var arr2 =arr.concat()
    arr2[0] = 5
    arr2[2].name = '修改'
    console.log(arr)
    console.log(arr2)

JS深拷贝与浅拷贝_第5张图片

方法3 Array.prototype.clice()
    var arr = [1,2,{name:'array拷贝'}]
    var arr2 = arr.slice()
    arr2[0] = 5
    arr2[2].name = '修改'
    console.log(arr)
    console.log(arr2)

JS深拷贝与浅拷贝_第6张图片

关于Array的slice和concat方法的补充说明:
Array的slice和concat方法不修改原数组,
只会返回一个浅复制了原数组中的元素的一个新数组。

深拷贝

方法1 Json.parse(Json.stringify())
    var arr = [1,2,{name:'kobe'}]
    var arr2 = JSON.parse(JSON.stringify(arr))
    arr2[0] = 5
    arr2[2].name = 'new'
    console.log(arr)
    console.log(arr2)

JS深拷贝与浅拷贝_第7张图片

注意!!!!!!!!!!!!!!!!!!
 Json.parse(Json.stringify())可以实现深拷贝,但无法拷贝函数
    var obj = {
        name:'kobe',
        a:{
            a:'子对象'
        },
        function(){
            return console.log(13)
        }
    }
    var obj2 = JSON.parse(JSON.stringify(obj))
    obj2.name = 'new'
    obj2.a.a = 'new'
    console.log(obj)
    console.log(obj2)

JS深拷贝与浅拷贝_第8张图片

方法2 递归
    var obj = {
        name: 'kobe',
        a: {
            a: '子对象'
        },
        function() {
            return console.log(13)
        }
    }
    //检测数据类型
    function type(target) {
        return Object.prototype.toString.call(target).slice(8,-1)
    }
    //递归函数
    function clone(target){
        let result,targetType = type(target)
        if( targetType === 'Object' ){
            result = {}
        }else if(targetType === 'Array'){
            result = []
        }else{
            return target
        }
        for( let i in target ){
            let value = target[i]
            if( type(value) === 'Object' || type(value) === 'Array' ){
                result[i] = clone(value)
            }else{
                result[i] = value
            }
        }
        return result
    }
    clone(obj)
    var obj2 = clone(obj)
    obj2.name = 'new'
    obj2.a.a = '新的子对象'
    console.log(obj)
    console.log(obj2)

JS深拷贝与浅拷贝_第9张图片

方法3 原型
    var obj = {
        name: 'kobe',
        a: {
            a: '子对象'
        },
        function() {
            return console.log(13)
        }
    }
    function clone(obj){
        if( obj !== 'null' && typeof obj !== 'object' ){
            return obj
        }
        let nObj = new obj.constructor()
        for( let key in obj ){
            if( obj.hasOwnProperty(key) ){
                nObj[key] = clone(obj[key])
            }
        }
        return nObj
    }
    var obj2 = clone(obj)
    obj2.name = 'new'
    obj2.a.a = '新的子对象'
    console.log(obj)
    console.log(obj2)

JS深拷贝与浅拷贝_第10张图片

你可能感兴趣的:(js)