js对象、数组拷贝

        在js中,数据类型类型可分为值类型(基本类型)和引用类型。值类型有:字符串(String)、布尔(Boolean)、数字(Number)、对空(Null)、未定义(undefined)、Symbol。引用类型:对象(Object)、数组(Array)、函数(Function)。这两种类型的不同,使得在拷贝的时候也会有差异。值类型拷贝的时候直接赋值就好,但是在引用类型的对象和数组中,如果直接整体赋值的话有的时候是会有问题的。在项目中,我们经常需要保存一份原始数据,然后拷贝一份原始数据进行更改,那么如果这个数据是Object或者Array类型,我们直接拷贝的话,他们还是指向的同一个地址,所以,当我们改变其中的一个值或者新增一个属性时,另一份也会跟着变化,这肯定不是我们想要的结果,那么今天就总结一下js中,对象、数组拷贝的问题。

        拷贝的问题也是分为两种,一种是浅拷贝、另一种是深拷贝。在总结之前,我们先定义一个较复杂的对象名为Obj,后面的代码都是使用该对象进行更改的,具体结构如下:

let Obj = {

    name:'zhang',

    age:18,

    score:{

        Chinese:98,

        English:88,

        Math:98

    },

    like:[{

            sports:5

          },

        {

            sports:4

        },{

            sports:3

        }]

}

一、浅拷贝

1、浅拷贝之使用Object.assign方式

function ObjCopy1(){

    let Obj1 = Object.assign({},Obj,);

    Obj1.name = 'zhang1';

    Obj1.like[1].sports = 55;

    Obj1.score.Chinese = 100,

    console.log('Obj.name:',Obj.name,' Obj.like[1].sports:',Obj.like[1].sports,'      Obj.score.Chinese:',Obj.score.Chinese);

    console.log('Obj1.name:',Obj1.name,'  Obj1.like[1].sports',Obj1.like[1].sports,'      Obj1.score.Chinese:',Obj1.score.Chinese);

}

ObjCopy1();


Object.assign浅拷贝结果

2、浅拷贝之...运算符实现

function ObjCopy2(){

    let Obj2 = {...Obj};

    Obj2.name = 'zhang1';

    Obj2.like[1].sports = 55;

    Obj2.score.Chinese = 100,

    console.log('Obj.name:',Obj.name,'  Obj.like[1].sports:',Obj.like[1].sports,'      Obj.score.Chinese:',Obj.score.Chinese);

    console.log('Obj2.name:',Obj2.name,'  Obj2.like[1].sports',Obj2.like[1].sports,'      Obj2.score.Chinese:',Obj2.score.Chinese);

}

ObjCopy2();


...运算符浅拷贝结果

3、浅拷贝之一重循环直接遍历

function ObjCopy3(Obj){

    let Obj3={};

    for (let item in Obj){

        Obj3[item] = Obj[item]

    }

    Obj3.name = 'zhang1';

    Obj3.like[1].sports = 55;

    Obj3.score.Chinese = 100,

    console.log('Obj.name:',Obj.name,'  Obj.like[1].sports:',Obj.like[1].sports,'      Obj.score.Chinese:',Obj.score.Chinese);

    console.log('Obj3.name:',Obj3.name,'  Obj3.like[1].sports',Obj3.like[1].sports,'      Obj3.score.Chinese:',Obj3.score.Chinese);

}

一重循环遍历浅拷贝结果

        通过结果可以看到,通过以上三种方式实现的拷贝都是浅拷贝,当嵌套多层Object或Array时,我们更改value中的对象或Array的值时,原始数据也跟着变化了。

二、深拷贝

1、深度拷贝之使用JSON.parse()和JSON.stringify()

function ObjCopy4(){

    let Obj4 = JSON.parse(JSON.stringify(Obj));

    Obj4.name = 'zhang1';

    Obj4.like[1].sports = 55;

    Obj4.score.Chinese = 100,

    console.log('Obj.name:',Obj.name,'  Obj.like[1].sports:',Obj.like[1].sports,'      Obj.score.Chinese:',Obj.score.Chinese);

    console.log('Obj4.name:',Obj4.name,'  Obj4.like[1].sports',Obj4.like[1].sports,'      Obj4.score.Chinese:',Obj4.score.Chinese);

}

ObjCopy4();

利用JSON.parse()和JSON.stringify()  方法拷贝结果

2、利用递归,自定义深度拷贝

function ObjCopy5(){

function copy (Obj) {

        var newObj = Obj.constructor === Array ? [] : {};

        if(typeof Obj !== 'object'){

            return;

        }

        for(var i in Obj){

          newObj[i] = typeof Obj[i] === 'object' ?

          copy(Obj[i]) : Obj[i];

        }

        return newObj

}

var Obj5 = copy(Obj)

Obj5.name = 'zhang1';

Obj5.like[1].sports = 55;

Obj5.score.Chinese = 100,

console.log('Obj.name:',Obj.name,'  Obj.like[1].sports:',Obj.like[1].sports,'  Obj.score.Chinese:',Obj.score.Chinese);

console.log('Obj5.name:',Obj5.name,'  Obj5.like[1].sports',Obj5.like[1].sports,'  Obj5.score.Chinese:',Obj5.score.Chinese);

}

递归方法实现深度拷贝

        这两种方法都能实现深度拷贝,此处只是针对Object和Array,Function的不一定能够拷贝成功。一般情况下针对只含有Object和Array的对象拷贝时,使用JSON.parse()和JSON.stringify()方法拷贝是非常简单的。此处我只总结了5种方法,如果有其它的方法,也希望大家能够多分享哦。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容