es3,es5,es6[对象的深浅拷贝] ②深拷贝

在上一篇文章中我们探讨了浅拷贝的知识,这一篇我们来讲一下深拷贝的原理。

递归方法

我们要知道深拷贝是在浅拷贝的基础之上的,而浅拷贝对嵌套的数据就没办法比如:var obj = { a: 1, b: { c: 3, d: { e: 5 } } }
对于这个对象我们可这样处理

function sClone(obj) {
            var cloneObj = {};
            for (var i in obj) {
                if (typeof obj[i] === 'object' && obj[i] !== null) {
                    cloneObj[i] = {};
                    for (var j in obj[i]) {
                        if (typeof obj[i][j] === 'object' && obj[i][j] !== null) {
                            cloneObj[i][j] = {};
                            for (var k in obj[i][j]) {
                                cloneObj[i][j][k] = obj[i][j][k]
                            }
                        } else {
                            cloneObj[i][j] = obj[i][j]
                        }
                    }

                } else {
                    cloneObj[i] = obj[i]
                }
            }
            return cloneObj;
        }

这里面的核心思想只有一个就是循环嵌套,一直把引用数据类型的数据,转到简单数据类型,有几层数据就转几次,然后就复制简单数据类型,很明显这一点都不合理,因为你根本不可能知道你的数据有几层嵌套,而且还要做数组的判断,因为数据的存储中最常用的就是数组和对象的混用,还要嵌套几层。
很多人觉得这不可能现实中不会有人这么用的。其实混用的才是常见的。因为一般来说对于数据的集合我们用数组,数据的描述我们使用对象。比方说一个学校的班级使用数组,班级里的人名用数组,但是每个人一般要用对象来形容。所以混用嵌套是很普遍的。
回归正题我们在不清楚有几层的时候,我们又想写的简单一点需要用什么呢,没错就是递归,也就是自己调用自己,如果不清楚有多少层,就加判断,只要没到简单数据类型就递归就可以了。
于是就可以这样:

 function sClone(obj, cloneObj) {
            var cloneObj = cloneObj || {};

            for (var i in obj) {
                if (typeof obj[i] === 'object' && obj[i] !== null) {
                    cloneObj[i] = {};
                    sClone(obj[i], cloneObj[i])
                } else {
                    cloneObj[i] = obj[i];
                }
            }
            return cloneObj;

        } 

这里的思路就是首先把对象代进去,然后循环,如果是对象就递归继续循环,如果是简单数据类型就拷贝。
然后我们还要加上数组的判断:

  function sClone(obj, cloneObj) {
            var cloneObj = cloneObj || {};

            for (var i in obj) {
                if (typeof obj[i] === 'object' && obj[i] !== null) {
                    cloneObj[i] = Array.isArray(obj[i]) ? [] : {};
                    sClone(obj[i], cloneObj[i])
                } else {
                    cloneObj[i] = obj[i];
                }
            }
            return cloneObj;

        }

JSON互转

同时我们还有一种方法就是使用JSON.stringify和JSON.parse互转实现深拷贝。其中JSON.stringify是将对象转为一个字符串,JSON.parse是将一个字符串转换为一个新对象
这里的原理我简单说一下,因为我们深拷贝的方法实际上是创建了一个对象然后将原对象的所有属性赋到了新对象上面,并返回新对象。如果不这么做的话,那么这两个对象其实都是持有同一引用,换句话说深拷贝只需要注意两点核心。第一将引用切断,也就是新对象和原来的对象不能有任何关系,第二点我们需要保证原有的对象中的所有属性在新对象中都要出现。所以我们通过JSON.stringify和JSON.parse互转所产生的新对象就是和原对象是没有任何关系的,同时原对象的所有值都会在新对象中出现。而且这种方法也很简单

 function sClone(obj) {
            return JSON.parse(JSON.stringify(obj))
        }

但是呢这个问题虽然简单但是是有着问题的。因为使用JSON.stringify()以及JSON.parse()它是不可以拷贝 undefined , function, RegExp 等等类型的,所以如果你的需求是比较严格的话还是不要使用这种方法。

Jquery方法

在jq中其实也已经提供给我们的方法了就是extend
jQuery.extend([deep], target, object1) 函数用于将一个或多个对象的内容合并到目标对象。deep可选。 Boolean类型 指示是否深度合并对象,默认为false。如果该值为true,就是深拷贝。target目标对象,其他对象的成员属性将被附加到该对象上。object1被合并对象。

  function sClone(obj) {
            return $.extend(true,{},obj)
        }

就是这样,他的本质还是使用的递归思路解决的问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值