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种方法,如果有其它的方法,也希望大家能够多分享哦。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,992评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,212评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,535评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,197评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,310评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,383评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,409评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,191评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,621评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,910评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,084评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,763评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,403评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,083评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,318评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,946评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,967评论 2 351

推荐阅读更多精彩内容