前端拷贝的几种方式

687 阅读2分钟

只能拷贝对象的第一层的相关拷贝方法(浅拷贝,第二层还是指向原来的地址)

只能拷贝对象的第一层,如果对象中的属性也是对象的话(第二层),第二层指向原来的地址

...延展操作符

代码:

function deep_clone_point () {
    const obj1 = {
        a: 'a',
        b: 'ab',
        c: {
            cc: 'cc',
            cd: 'cd'
        }
    }
    const obj_clone = {...obj1}
    obj_clone['a'] = 1;
    obj_clone['c']['cc'] = 'ccc'
    console.log('=======>obj1',obj1)
    console.log('=======>obj_clone',obj_clone)
}

结果:

image.png

for in 循环遍历对象

代码:

function deep_clone_for () {
    const obj1 = {
        a: 'a',
        b: 'ab',
        c: {
            cc: 'cc',
            cd: 'cd'
        }
    }
    let obj_clone = {}
    for (const key in obj1) {
        obj_clone[key] = obj1[key]
    }
    obj_clone['a'] = 'aa';
    obj_clone['c']['cc'] = 'cccc'
    console.log('=======>obj1',obj1)
    console.log('=======>obj_clone',obj_clone)
}

结果:

image.png

Object.assign() 对象的合并

代码:

function deep_clone_assign () {
    const obj1 = {
        a: 'a',
        b: 'ab',
        c: {
            cc: 'cc',
            cd: 'cd'
        }
    }
    var obj_clone = Object.assign({},obj1);
    obj_clone['a'] = 'clone';
    obj_clone['c']['cc'] = 'cloned'
    console.log('=======>obj1',obj1)
    console.log('=======>obj_clone',obj_clone)
}

结果:

image.png

slice方法(数组的方法)

可以看到,第二层的无论是obj还是arr,都是指向原来的地址

代码:

function deep_clone_slice () {
    const array1 = ['a', 'b', {c: 'c'}, ['d','e']]

    const arrat_clone = array1.slice()
    arrat_clone[0] = 'clone';
    arrat_clone[2]['c'] = 'cloned'
    arrat_clone[3][0] = 'cloned_two'
    console.log('=======>array1',array1)
    console.log('=======>arrat_clone',arrat_clone)
}

结果:

image.png

concat方法

代码:

function deep_clone_concat () {
    const array1 = ['a', 'b', {c: 'c'}, ['d','e']]

    const array_clone = array1.concat()
    array_clone[0] = 'clone';
    array_clone[2]['c'] = 'cloned'
    array_clone[3][0] = 'cloned_two'
    console.log('=======>array1',array1)
    console.log('=======>arrat_clone',array_clone)
}

结果:

image.png

递归

深拷贝,是拷贝对象各个层级的属性

代码:

function deep_clone_digui(obj) {
    let obj_clone = Array.isArray(obj) ? [] : {};
    if(obj && typeof obj === "object"){
        for(key in obj){
            if(obj.hasOwnProperty(key)){
                //判断obj子元素是否为对象,如果是,递归复制
                if(obj[key] && typeof obj[key] === "object"){
                    // 这里我们的递归使用一个js的调用函数自己的api
                    obj_clone[key] = arguments.callee(obj[key]);
                }else{
                    //如果不是,简单复制
                    obj_clone[key] = obj[key];
                }
            }
        }
    }
    return obj_clone;
}
function deep_clone_digui_test() {
    const array1 = ['a', 'b', {c: 'c'}, ['d','e']]
    const array_clone = deep_clone_digui(array1)
    array_clone[0] = 'clone';
    array_clone[2]['c'] = 'cloned'
    array_clone[3][0] = 'cloned_two'
    console.log('=======>array1',array1)
    console.log('=======>arrat_clone',array_clone)
}

结果:

image.png

Json.stringify和Json.parse

当值为undefined、function、symbol、RegExp会在转换过程中被忽略,所以它有局限性

代码:

function deep_clone_json () {
    const obj1 = {
        a: 'a',
        b: 'ab',
        c: {
            cc: 'cc',
            cd: 'cd'
        }
    }
    const obj_clone = JSON.stringify(obj1)
    const obj_clone_parse =JSON.parse(obj_clone)
    obj_clone_parse['a'] = 1;
    obj_clone_parse['c']['cc'] = 'ccc'
    console.log('=======>obj_clone',obj_clone)
    console.log('=======>obj_clone_parse',obj_clone_parse)
}

结果:

image.png

函数库lodash的_.cloneDeep方法

代码:

function deep_clone_loadsh () {
    const _ = require('lodash')
    const obj1 = {
        a: 'a',
        b: 'ab',
        c: {
            cc: 'cc',
            cd: 'cd'
        }
    }
    const obj_clone = _.cloneDeep(obj1)
    console.log('=======>obj_clone',obj_clone === obj1); //false
    obj_clone['a'] = 1;
    obj_clone['c']['cc'] = 'ccc'
    console.log('=======>obj1',obj1)
    console.log('=======>obj_clone',obj_clone)
}

结果:

image.png

通过JQuery的extend方法实现深拷贝

$.extend( [deep ], target, object1 [, objectN ] )

  • deep

表示是否深拷贝,为true为深拷贝,为false,则为浅拷贝

  • target

 Object类型 目标对象,其他对象的成员属性将被附加到该对象上。

  • object1 objectN

可选。 Object类型 第一个以及第N个被合并的对象。

代码:

function deep_clone_jq () {
    const _ = require('jquery')
    const obj1 = {
        a: 'a',
        b: 'ab',
        c: {
            cc: 'cc',
            cd: 'cd'
        }
    }
    const obj_clone = $.extend(true, {}, obj1);
    console.log('=======>obj_clone',obj_clone === obj1); //false
    obj_clone['a'] = 1;
    obj_clone['c']['cc'] = 'ccc'
    console.log('=======>obj1',obj1)
    console.log('=======>obj_clone',obj_clone)
}