json方法实现拷贝有什么问题?_关于js深拷贝与浅拷贝的区别,实现深拷贝的几种方法...

数据深拷贝是实际项目中你总有一天或者必然会遇到的问题,甚至很多人可能对这两个概念并不是很清晰。简单来说,深拷贝就是把一条数据A复制出来个副本B,修改副本B数据并不会影响原来数据A,浅拷贝则反之,修改数据B会影响到原来的A数据。下面总结下有些处理深拷贝的方法(下列方法demo均来自于互联网,本文章主要用于总结归档,方便后人查阅)

浅拷贝

let a=[0,1,2,3,4],    b=a;console.log(a===b);a[0]=1;console.log(a,b);

1444147d3a4058033117d0068645649b.png

为什么会出现上面这种情况?

那么这里,就得引入基本数据类型与引用数据类型的概念了。面试常问,基本数据类型有哪些,number,string,boolean,null,undefined,symbol以及未来ES10新增的BigInt(任意精度整数)七类。引用数据类型(Object类)有常规名值对的无序对象{a:1},数组[1,2,3],以及函数等。

实现简单的深拷贝

1、slice和concat

这两个方法特性是将原来的数据产生一个副本,不会去改变原来的数据,但它有一定的局限性,如果数据是基本数据类型,那是可以的,否则,就会有问题。

var a= [0,1,2,3,4];var b= a.slice(0); // 通过slice方法,参数为0,意味着拷贝数组arr1的0 - 最后一位b[1] = "9";

1f97653c7c76ce86ce1230f0b5d69afb.png

2、Object.assign()方法

这个方法和上面的slice和concat方法有同样的弊端

var Jack ={    code:'0001',    name:'张三',    assing:function () {        alert('张三签到');    },    car:{        name:'路虎',        type:'SVR'    }} var Tom = Object.assign({},Jack);Tom.name = '赵四';console.log(Jack);console.log(Tom);Tom.car.name='宝马';console.log(Jack);console.log(Tom);

65823294786d230ca55912736465aaf1.png

3、Json.parse(Json.stringify(obj))方式

我太难了,看了上面几种方法,都不能达到要求,那么Json.parse又会如何呢?该方法成功实现了嵌套属性的深拷贝,但是原对象中的assign()方法丢失了。这是因为JSON.stringify()方法将对象转化为字符串,但只会处理简单属性和简单属性数组,constructor属性丢失了。也就是说他中间变换了形态,从对象—>字符串—>对象,最终把原对象该有的自身方法弄丢了,如果你不介意,自然是可以的,因此,除非对象只有简单属性,没有constructor信息,才能使用Json.parse(Json.stringify(obj))做深拷贝。

var Alex = JSON.parse(JSON.stringify(Jack));Alex.name='王五';Alex.car.name='劳斯莱斯';console.log(Jack);console.log(Alex);

65e140bfc1de350b118d2e4669e95e5a.png

4、es6中的 Object.create()方法

function deepClone(initalObj, finalObj) {      var obj = finalObj || {};      for (var i in initalObj) {            var prop = initalObj[i];  // 避免相互引用对象导致死循环,如initalObj.a = initalObj的情况    if(prop === obj) {                  continue;    }            if (typeof prop === 'object') {      obj[i] = (prop.constructor === Array) ? [] : Object.create(prop);    } else {      obj[i] = prop;    }  }      return obj;}

那么到底如何实现复杂的数据结构深拷贝?

自己封装个简单方法是个不错的选择

function deepClone(obj) {    let objClone = Array.isArray(obj) ? [] : {};    if (obj && typeof obj === "object") {        for (key in obj) {            if (obj.hasOwnProperty(key)) {                //判断ojb子元素是否为对象,如果是,递归复制                if (obj[key] && typeof obj[key] === "object") {                    objClone[key] = deepClone(obj[key]);                } else {                    //如果不是,简单复制                    objClone[key] = obj[key];                }            }        }    }    return objClone;}var obj1 = {    a: 1,    b: [{ x: 1, y: 2 }],    c: {        d: [{bb: 100}]    }}var obj2 = deepClone(obj1);obj2.a = 3;obj2.b[0].x = 10;obj2.b[0].y = 20;obj2.c.d[0].bb = 200;console.log(obj1,obj2)

50708fd4d4070b5fd9eeb5b1c699b806.png

借助函数库lodash实现深拷贝

这个方法库特别强大,可以极大的提高工作中处理数据效率。

var objects = [{ 'a': 1 }, { 'b': 2 }]; var deep = _.cloneDeep(objects);console.log(deep[0] === objects[0]);// => false

小结

说了这么多,了解深拷贝也不仅仅是为了应付面试题,在实际开发中也是非常有用的。例如后台返回了一堆数据,你需要对这堆数据做操作,但多人开发情况下,你是没办法明确这堆数据是否有其它功能也需要使用,直接修改可能会造成隐性问题,深拷贝能帮你更安全安心的去操作数据,根据实际情况来使用深拷贝,大概就是这个意思。

c1495ca786c62b6dc6f0414e25ccf935.png 92b454b47408b15ca3cef1b998d93ac6.png微信号:gh_dcd05cdf3c3e扫码关注我们,获取最新资讯
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值