Javascript中的深复制

矮脚虎
• 阅读 1873

对一个对象或者数组这种引用类型的值进行复制可以分为浅复制和深复制,比如这样的一个对象

let obj={
    a:1,
    b:{
        a:1,
        b:2
    },
    c:3
}

很明显这个对象是存在两层的,obj[b]不是基本类型值,而是另一个对象。如果使用浅复制去拷贝这个对象的话,那么拷贝出来新的对象的b属性的值是原来对象b属性的引用地址,也就是说,如果改变源对象的b属性,新的对象也会受到影响,因为我们只使用浅复制拷贝了一层。


上面讲的就是浅复制,在实际应用中存在很严重的问题。所以我们一般复制对象都是用深复制,深复制不是简单的复制一层,而是遍历整个对象,一直到获取到的值不是引用类型,而是基本类型的时候才进行复制,这样就使得新的对象跟原来的对象完全是两个不同的对象了。


下面是我写的一个简单的深复制函数

let obj={
    a:1,
    b:{
        a:1,
        b:2
    },
    c:3
}

function deepClone(object){
    let obj=new Object();
    if(object instanceof Object){
//         说明是对象
        for(let attr in object){
            if(object.hasOwnProperty(attr)){
//                 过滤基本类型值
                if(typeof object[attr]!='object'||object[attr]==null){
                    obj[attr]=object[attr];
                }else{
                    obj[attr]=deepClone(object[attr]);
                }
            }
        }
    }
    return obj;
}

let obj2=deepClone(obj);
obj.b=1;
console.log(obj,obj2);

注意,这个函数是存在问题的,因为这个函数只能处理纯对象类型,也就是说属性中包含数组的对象该方法是无法处理的。


下面这里有一个方法是stackoverflow上的答案,兼容了数组与对象的

function clone(obj) {
    var copy;

    // Handle the 3 simple types, and null or undefined
    if (null == obj || "object" != typeof obj) return obj;

    // Handle Date
    if (obj instanceof Date) {
        copy = new Date();
        copy.setTime(obj.getTime());
        return copy;
    }

    // Handle Array
    if (obj instanceof Array) {
        copy = [];
        for (var i = 0, len = obj.length; i < len; i++) {
            copy[i] = clone(obj[i]);
        }
        return copy;
    }

    // Handle Object
    if (obj instanceof Object) {
        copy = {};
        for (var attr in obj) {
            if (obj.hasOwnProperty(attr)) copy[attr] = clone(obj[attr]);
        }
        return copy;
    }

    throw new Error("Unable to copy obj! Its type isn't supported.");
}


还有一种比较抖机灵的做法就是

var cloneOfA = JSON.parse(JSON.stringify(a));

这种做法也是可以实现深复制,但是由于JSON.stringify()方法在遇到undefined值时会省略对应的属性,所以这个方法不太推荐使用,存在问题。


基于jQ的做法是这样的

var copiedObject = jQuery.extend({}, originalObject) // shallow copy浅复制

var copiedObject = jQuery.extend(true, {}, originalObject) // deep copy深复制
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
java 复制Map对象(深拷贝与浅拷贝)
java复制Map对象(深拷贝与浅拷贝)CreationTime2018年6月4日10点00分Author:Marydon1.深拷贝与浅拷贝  浅拷贝:只复制对象的引用,两个引用仍然指向同一个对象
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Karen110 Karen110
3年前
一篇文章带你了解JavaScript日期
日期对象允许您使用日期(年、月、日、小时、分钟、秒和毫秒)。一、JavaScript的日期格式一个JavaScript日期可以写为一个字符串:ThuFeb02201909:59:51GMT0800(中国标准时间)或者是一个数字:1486000791164写数字的日期,指定的毫秒数自1970年1月1日00:00:00到现在。1\.显示日期使用
美凌格栋栋酱 美凌格栋栋酱
6个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Jacquelyn38 Jacquelyn38
4年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Stella981 Stella981
3年前
SpringBoot学习:整合shiro自动登录功能(rememberMe记住我功能)
首先在shiro配置类中注入rememberMe管理器!复制代码(https://oscimg.oschina.net/oscnet/675f5689159acfa2c39c91f4df40a00ce0f.gif)/cookie对象;rememberMeCookie()方法是设置Cookie的生成模
Wesley13 Wesley13
3年前
Java深拷贝和浅拷贝
1.浅复制与深复制概念⑴浅拷贝(浅克隆)   复制出来的对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。⑵深拷贝(深克隆)   复制出来的所有变量都含有与原来的对象相同的值,那些引用其他对象的变量将指向复制出来的新对象,而不再是原有的那些被引用的对象。换言之,深复制
Stella981 Stella981
3年前
JS 对象数组Array 根据对象object key的值排序sort,很风骚哦
有个js对象数组varary\{id:1,name:"b"},{id:2,name:"b"}\需求是根据name或者id的值来排序,这里有个风骚的函数函数定义:function keysrt(key,desc) {  return function(a,b){    return desc ? ~~(ak
Easter79 Easter79
3年前
SpringBoot学习:整合shiro自动登录功能(rememberMe记住我功能)
首先在shiro配置类中注入rememberMe管理器!复制代码(https://oscimg.oschina.net/oscnet/675f5689159acfa2c39c91f4df40a00ce0f.gif)/cookie对象;rememberMeCookie()方法是设置Cookie的生成模
Python进阶者 Python进阶者
1年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这