结合多个实例深入理解js的深拷贝和浅拷贝,多种方法实现对象的深拷贝


声明:本文转载自https://my.oschina.net/u/2542841/blog/2961340,转载目的在于传递更多信息,仅供学习交流之用。如有侵权行为,请联系我,我会及时删除。

亲们为什么要研究深拷贝和浅拷贝呢,因为我们项目开发中有许多情况需要拷贝一个数组抑或是对象,但是单纯的靠=“赋值”并不会解决所有问题,如果遇到引用类型的对象改变新赋值的对象会造成原始对象也发生同样改变,而要去除影响就必须用到深拷贝,深拷贝,对于引用对象需要进行深拷贝才会去除影响。如果是值类型直接“=”就好。

1.引用类型  引用类型通常叫做类(class),也就是说,遇到引用值,所处理的就是对象。new 出来的对象都是引用对象

(1)值类型:String, 数值、布尔值、null、undefined。 对于值类型一个对象一个存储位置所以会互不干扰

(2)引用类型:对象、数组、函数。对于引用类型,a=b赋值后的新对象也指向同一个存储地址所以b变化a跟随变化

而要改变这种情况需要改变b的指向,使其指向b存储位置如下图

下面是各种实例对比:

第一模块-数组:

数组浅拷贝:

a =[1,2,3];b=a;b.push('change');console.log('a:'+a,'b:'+b)
VM529:1 a:1,2,3,change b:1,2,3,change

数组深拷贝://到每一项都是值类型时可以直接赋值

a =[1,2,3];a.forEach(val => b.push(val));b.push('change');console.log('a:'+a,'b:'+b)
VM529:1 a:1,2,3,change,1,2,3,change,1,2,3,change

第二模块-对象:

1-1对象浅拷贝的代码及结果

bb改变后原数组aa也跟随变化,根本原因就是像第一张线框图描述的一样

1-2对象深拷贝代码及结果,使用es6的Object.assign()方法

深拷贝bb不会影响aa

1-3对象深拷贝使用JSON.parse(JSON.stringify(obj)),即对象序列化

1-4对象深拷贝使用es6的Object.keys(obj),Object.values(obj)分别获得键数组和值数组,再通过函数根据条件循环回调deal()得到深拷贝值:《推荐使用回调》,留下个小问题,看官们可以试着这个思路去完成数组和函数回调实现深拷贝。

可复制代码:

aa = {
    key:'1',
    value:'a',
    children:{
        key: '2',
        value: 'b'
    }
};

function deal(obj) {
    bb = {};
    let keyArr = Object.keys(obj);
    let valueArr = Object.values(obj);
    valueArr.forEach((val,index) => {
        if(Object.prototype.toString.call(val) === "[object  Object]") {
            deal(val)
        }else {
            bb[keyArr[index]] = val
        }
    })
    return bb
}
let BB = {}
BB=deal(aa);
BB['add']='addStr';
console.log('aa:',aa,'========','BB:',BB)

截图代码和结果:

第三模块对于对象来说可复制的深拷贝代码和结果事例如下:

实例一

aa = {
    key:'1',
    value:'a',
    children:{
        key: '2',
        value: 'b'
    }
};
bb=aa;bb['add']='addStr';console.log('aa:',aa,'====','bb',bb)
VM1098:9 aa: {key: "1", value: "a", children: {…}, add: "addStr"}add: "addStr"children: key: "2"value: "b"__proto__: Objectkey: "1"value: "a"__proto__: Object ==== bb {key: "1", value: "a", children: {…}, add: "addStr"}add: "addStr"children: key: "2"value: "b"__proto__: Objectkey: "1"value: "a"__proto__: Object

 

实例二
aa = {
    key:'1',
    value:'a',
    children:{
        key: '2',
        value: 'b'
    }
};
bb = {}
bb=Object.assign({},aa);bb['add']='addStr';console.log('aa:',aa,'====','bb',bb)
VM1223:10 aa: {key: "1", value: "a", children: {…}}children: key: "2"value: "b"__proto__: Objectkey: "1"value: "a"__proto__: Object ==== bb {key: "1", value: "a", children: {…}, add: "addStr"}add: "addStr"children: key: "2"value: "b"__proto__: Objectconstructor: ƒ Object()hasOwnProperty: ƒ hasOwnProperty()isPrototypeOf: ƒ isPrototypeOf()propertyIsEnumerable: ƒ propertyIsEnumerable()toLocaleString: ƒ toLocaleString()toString: ƒ toString()valueOf: ƒ valueOf()__defineGetter__: ƒ __defineGetter__()__defineSetter__: ƒ __defineSetter__()__lookupGetter__: ƒ __lookupGetter__()__lookupSetter__: ƒ __lookupSetter__()get __proto__: ƒ __proto__()set __proto__: ƒ __proto__()key: "1"value: "a"__proto__: Object

实例三
aa = {
    key:'1',
    value:'a',
    children:{
        key: '2',
        value: 'b'
    }
};
bb = {}
bb=JSON.parse(JSON.stringify(aa));bb['add']='addStr';console.log('aa:',aa,'====','bb',bb)
VM1653:10 aa: {key: "1", value: "a", children: {…}}children: key: "2"value: "b"__proto__: Objectkey: "1"value: "a"__proto__: Object ==== bb 

欢迎转载,转载请注明出处。欢迎大家交流学习

本文发表于2018年11月27日 15:00
(c)注:本文转载自https://my.oschina.net/u/2542841/blog/2961340,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除.

阅读 1521 讨论 0 喜欢 0

抢先体验

扫码体验
趣味小程序
文字表情生成器

闪念胶囊

你要过得好哇,这样我才能恨你啊,你要是过得不好,我都不知道该恨你还是拥抱你啊。

直抵黄龙府,与诸君痛饮尔。

那时陪伴我的人啊,你们如今在何方。

不出意外的话,我们再也不会见了,祝你前程似锦。

这世界真好,吃野东西也要留出这条命来看看

快捷链接
网站地图
提交友链
Copyright © 2016 - 2021 Cion.
All Rights Reserved.
京ICP备2021004668号-1