对象的深复制

  • 源对象的属性更改,不会引起复制后的对象个属性的更改
  • 源对象的任何属性与子属性与新对象的之间没有任何引用关系

Coding:

/*
  对象的深复制:
    1 初始化目标对象
        如果没有指定目标对象,则利用源对象的构造函数创建目标对象,判断源对象类型,正则对象和日期对象分开复制
            如果源对象是正则对象,抽取源对象属性source和flag放入构造参数中新建目标对象
            如果源对象是日期对象,抽取源对象放入构造参数中新建目标对象
    2 复制属性并返回结果
        以数组形式获取源对象的所有属性名
        遍历数组,获取每个属性名对象的属性描述对象
        如果属性值是对象:
            将源对象的属性描述对象设置到对应的目标对象属性里面去
            考虑到属性对象可能存在嵌套,将当前属性value设置为属性描述对象value的递归遍历结果
        如果属性值是函数:
            正则提取函数参数和函数体内容,使用构造函数创建的形式将参数传进去
            设置value为fn,其他三个描述属性参照描述属性对象
        如果属性值不是函数也不是对象,只是普通属性,那么直接将源属性对应的属性名和属性描述设置给目标属性
*/
        function cloneObject(sourceObj, targetObj) {
            if (!sourceObj) return {};
            if (!targetObj) {
                targetObj = new sourceObj.constructor();
                switch (targetObj.constructor) {
                    case RegExp:
                        targetObj = new RegExp(sourceObj.source, sourceObj.flag);
                        break;
                    case Date:
                        targetObj = new Date(sourceObj);
                        break;
                }
            }
            var names = Object.getOwnPropertyNames(sourceObj);
            for (var i = 0; i < names.length; i++) {
                var desc = Object.getOwnPropertyDescriptor(sourceObj, names[i]);
                if (typeof desc.value === "object") {
                    var o = cloneObject(desc.value);
                    Object.defineProperty(targetObj, names[i], {
                        configurable: desc.configurable,
                        enumerable: desc.enumerable,
                        writable: desc.writable,
                        value: o
                    });
                } else if (typeof desc.value === "function") {
                    var fnStr = desc.value.toString().replace(/\n/g, "");
                    //非贪婪匹配,满足情况只取一次
                    var arg = fnStr.match(/\((.*?)\)/)[1];
                    //贪婪匹配,取{}的任意字符
                    var content = fnStr.match(/{(.*)}/)[1];
                    var fn = new Function(arg, content);
                    //设置函数名
                    Object.defineProperty(fn, "name", {
                        writable: true,
                        value: desc.value.name
                    });
                    Object.defineProperty(targetObj, names[i], {
                        configurable: desc.configurable,
                        enumerable: desc.enumerable,
                        writable: desc.writable,
                        value: fn
                    });
                } else {
                    Object.defineProperty(targetObj, names[i], desc);
                }
            }
            return targetObj;
        }

运行结果:

JavaScript 对象的深复制的更多相关文章

  1. javascript中关于深复制与浅复制的问题

    在javascript中,变量的类型分为基本类型和引用类型. 对于基本类型的变量来说,值的复制以及作为函数参数实参传递的过程都是值的复制传递,换句话说,是会在内存中开辟出一个新空间用于存放新的值的.这 ...

  2. JavaScript对象的深浅复制

    前言 从层次上来看,对象的复制可以简单地分为浅复制和深复制,顾名思义,浅复制是指只复制一层对象的属性,不会复制对象中的对象的属性,对象的深复制会复制对象中层层嵌套的对象的属性. 在复制对象时,除了要复 ...

  3. Java中对象的深复制和浅复制详解

    1.浅复制与深复制概念 ⑴浅复制(浅克隆) 被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象.换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象. ⑵ ...

  4. Objective-C:OC内部可变对象和不可变对象的深(复制)拷贝问题思考:

    OC内部:可变对象和不可变对象的深(复制)拷贝问题思考:   不可变对象:  例如NSString对象,因为NSString对象是常量字符串,所以,不可以更改其内容,但是可以修改指向该字符串的指针指向 ...

  5. java对象实现深复制的方法

    p2 = (Person)org.apache.commons.lang3.ObjectUtils.cloneBean(p); Person p2 = new Person(); p2 = (Pers ...

  6. javascript 中的深复制 和 其实现方法

    首先,我们需要明白什么是深复制(侧重指对象方面)? 在javascript中,复制分为浅复制和深复制,个人理解,浅复制就是直接将引用复制,复制前后的两个对象指向同一个内存地址,对其中一个进行操作,另外 ...

  7. js 复制对象的深复制与浅复制

    1.潜复制(修改新对象会改变原对象) var baz = {a:'hello', b: {c:'my', d:'friend'}} var foo = baz foo.a="better&q ...

  8. C# 对象的深复制和浅复制

    2019年第一篇博客,好吧,又大了一岁了,继续加油吧. 正文: C# 中的对象,众所周知是引用类型,那么如何复制对象Object呢,我们来看看下面这段代码: public class User { p ...

  9. js 对象的深复制 解决不能复制undefined (递归)

    用普通的拷贝  JSON.parse和 JSON.stringify 进行对象拷贝是不会拷贝undefined //普通的拷贝   const obj = {         a: {         ...

随机推荐

  1. 【算法】状态压缩DP

    状态压缩DP是什么? 答:利用位运算(位运算比加减乘除都快!)来记录状态,并实现动态规划. 适用于什么问题? 答:数据规模较小:不能使用简单的算法解决. 例题: 题目描述 糖果店的老板一共有M 种口味 ...

  2. pycharm项目移植过程中遇到的问题

     调试中遇到三个问题: 问题1:Error running 'run_all_test': Cannot run program "C:\Users\Administrator\.virtu ...

  3. XMLHttpRequest: 网络错误 0x2ee4, 由于出现错误 00002ee4 而导致此项操作无法完成

    原因: IE11有默认设置安全策略,如果url需要证书,一发送请求IE11就会拒绝,因为ssl certificate(SSL证书) 是非法的 解决方案: (1)修改IE浏览器配置 - 用户使用的电脑 ...

  4. Hackintosh Issues 10.13.x

    Issuses 1: 出现禁行: (-v:) allcating 0x800 pages at 0x2000000 alloc type 2 Load kernal from stream Load ...

  5. usage: git remote add [<options>] <name> <url> -f, --fetch fetch the remote branches --tags import all tags and associated objects when fetching

    按照git官网提示输入 git pushgit remote add origin git@github.com:***3 / elm-1.git -u 链接git远程仓库 出现错误 usage: g ...

  6. 题解【洛谷P3951】[NOIP2017]小凯的疑惑

    题目描述 小凯手中有两种面值的金币,两种面值均为正整数且彼此互素.每种金币小凯都有 无数个.在不找零的情况下,仅凭这两种金币,有些物品他是无法准确支付的.现在小 凯想知道在无法准确支付的物品中,最贵的 ...

  7. Navicat图形更改表结构的时,设置外键时出现1452错误

    原文地址:http://www.mamicode.com/info-detail-1296600.html 提示1452错误,如下图所示. 然后百度了一下,得到了一个靠谱的答案: 这是因为表设置了外键 ...

  8. 理解javaBean

    1:什么是JavaBean 组件?使用JavaBean 组件有什么优点?答案:现在软件开发都已经转向了基于组件的开发,目前具备代表性的组件技术有微软的COM.COM+,有Sun 的JavaBean 和 ...

  9. shiro登录认证过程讲解

      先粘出登录的代码 1. 可以看到已经获取到了username和password ,为了接下来的认证过程,我们需要获取subject对象,也就是代表当前登录用户,并且要将username和passw ...

  10. (转载)Docker的boot2docker.iso镜像使用

    原文路径:https://blog.csdn.net/jiangjingxuan/article/details/54908272#commentsedit 在Docker首次启动时需要下载的一个bo ...