• 关于js浅拷贝和深拷贝例子和方法解析(概念 区别 方法 总结 使用)


    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8">
            <title></title>
        </head>
        <body>
            <script type="text/javascript">
                /*浅拷贝和深拷贝的概念和区别
                    浅拷贝和深拷贝都只针对于引用数据类型,浅拷贝只复制指向某个对象的指针,而不复制对象本身,
                    新旧对象还是共享同一块内存;但深拷贝会另外创造一个一模一样的对象,
                    新对象跟原对象不共享内存,修改新对象不会改到原对象;
                区别:浅拷贝只复制对象的第一层属性、深拷贝可以对对象的属性进行递归复制;
                */
               
                // 第一种方式:for···in只循环第一层 浅拷贝的方法
                // 只复制第一层的浅拷贝
                function simpleCopy(obj) {
                   let newObj = Array.isArray(obj) ? [] : {};
                   for (let i in obj) {
                   newObj[i] = obj[i];
                  }
                   return newObj;
                }
                
                let testobj = {
                   a: 1,
                   b: 2,
                   c: {
                         d: 3
                      }
                }
                let testobj2 = simpleCopy(testobj);
                testobj2.a = 3;
                testobj2.c.d = 4;
                // 单层
                console.log(testobj.a); // 1
                console.log(testobj2.a); // 3
                // 多层
                console.log(testobj.c.d); // 4
                console.log(testobj2.c.d); // 4
                
                // 第二种方式Object.assign方法浅拷贝一层
                // 第三种方法 = 赋值 解构赋值
    
                // 第一种方式:(递归拷贝) 深拷贝  WeakMap 对象是一组键/值对的集合,其中的键是弱引用的。其键必须是对象,而值可以是任意的
                // WeakMap 的 key 只能是 Object 类型。 原始数据类型 是不能作为 key 的(比如 Symbol)
                function deepClone(obj, hash = new WeakMap) {
                    // 先把特殊情况全部过滤 null undefined date reg
                    if (obj == null) return obj
                    if (typeof obj !== 'object') return obj
                    if (obj instanceof Date) return new Date()
                    if (obj instanceof RegExp) return new RegExp(obj)
                    // 判断 [] {} 是对象还是数组 typeof instanceof constructor
                    // 有拷贝后的直接返回
                    if (hash.has(obj)) {
                        return hash.get(obj) // 解决循环引用的问题
                    }
                    // new 的实现原理
                    let instance = new obj.constructor
                    // 制作一个映射表
                    hash.set(obj, instance)
                    // 把实例上的属性拷贝到这个对象身上,把原型链指向到原型对象上
                    for (let key in obj) {
                        // 不拷贝原型链上的属性
                        if (obj.hasOwnProperty(key)) {
                            instance[key] = deepClone(obj[key], hash)
                        }
                    }
                    return instance
                }
                /************上面是封装的深拷贝函数,下面是测试代码包含多种情况************/
                let obj = {}
                obj.a = 1
                obj.name = 'bob'
                console.log(deepClone(obj), 'obj') // {a: 1, name: "bob"} "obj"
    
                let obj2 = {}
                obj2.b = obj2
                let aa = {
                    age: 18,
                    name: obj2
                }
                console.log(deepClone(aa), '深度拷贝')
    
                let arr = [1, 2, 3, 4, undefined, null]
                console.log(deepClone(arr), 'arr') // [1, 2, 3, 4, undefined, null] "arr"
    
                let fuzaobj = {
                    a: {
                        b: null,
                        c: /a/,
                        d: undefined
                    },
                    b: function() {
                        console.log(this.a)
                    },
                    c: [{
                            a: 'c',
                            b: /b/,
                            c: undefined
                        },
                        'a',
                        3
                    ]
                }
                console.log(deepClone(fuzaobj), '复杂对象拷贝')
    
    
                // 第二种方式:简单版本深拷贝 JSON.parse(JSON.stringify(obj)) 
                function deepCloneSimple(obj) {
                    return JSON.parse(JSON.stringify(obj))
                }
    
                let test = {
                    a: 11,
                    name: 'pop'
                }
                let deeptest = deepCloneSimple(test)
                deeptest.a = 5;
                console.log(test.a); // 11
                console.log(deeptest.a); // 5
    
                let test2 = {
                    a: undefined,
                    b: /b/,
                    c: null,
                    d: 111,
                    e: 'ssrrs',
                    f: {
                        name: 'bob'
                    },
                    h: function() {
                        console.log(111)
                    }
                }
                console.log(deepCloneSimple(test2))
                // {
                //     b: {}
                //     c: null
                //     d: 111
                //     e: "ssrrs"
                //     f: {
                //         name: "bob"
                //     }
                // }
    
                // 第三种方式拷贝:Object.assign(target, source)
                function deepOnlyOneClone(obj) {
                    return Object.assign({}, obj);
                }
    
                let test3 = {
                    a: 1,
                    b: 2,
                    c: [1, 2, 3]
                }
                let test4 = Object.assign({}, test3);
                test4.c[1] = 5;
                console.log(test3.c); // [1, 5, 3]
                console.log(test4.c); // [1, 5, 3]
    
                let test5 = {
                    a: null,
                    b: /bbb/,
                    c: undefined,
                    d: function() {
                        console.log(111)
                    },
                    e: {
                        name: 'bob',
                        age: 10,
                        desc: {
                            pre: '1111',
                            qto: 'ahhha'
                        }
                    },
                    f: [1, 2, 3],
                    g: {
                        h: {
                            k: 100
                        }
                    }
                }
                let test6 = deepOnlyOneClone(test5)
                test5.a = 111;
                test6.a = 333;
                // 单层测试
                console.log(test5.a) // 111
                console.log(test6.a) // 333
                // 多层测试
                test5.e.name = 'piter';
                test6.e.name = 'sos';
                console.log(test5.e.name) // sos
                console.log(test6.e.name) // sos
                // 完整结构测试
                console.log(deepOnlyOneClone(test5), '只能拷贝一层')
                
                // 结论
                // 函数没必要拷贝因为函数拷贝还是函数
                // Object.assign(target, source) 当对象中只有一级属性,没有二级属性的时候,此方法为深拷贝,但是对象中有对象的时候,此方法,在二级属性以后就是浅拷贝
                // 使用JSON.stringify()以及JSON.parse()它是不可以拷贝undefined,function,RegExp 等等类型的
                // 深拷贝作用在引用类型上!例如:Object,Array
                // 深拷贝不会拷贝引用类型的引用,而是将引用类型的值全部拷贝一份,形成一个新的引用类型,这样就不会发生引用错乱的问题
                // 使得我们可以多次使用同样的数据,而不用担心数据之间会起冲突
                // 项目如需用到可以借助第三方库(lodash.cloneDeep)或者用递归拷贝,
            </script>
        </body>
    </html>

    代码整理总结,转载请注明出处谢谢合作!

  • 相关阅读:
    9天C#转Java学习过程,自己记录一下
    【分享】我们用了不到200行代码实现的文件日志系统,极佳的IO性能和高并发支持,附压力测试数据
    微信公众号第三方平台开发坑
    分享我们团队最近开发的微信公众号运营助手,可以在手机上回复粉丝留言
    分享一波会眨眼的壁纸
    idea连接服务器上传jar并运行
    ngnix简单使用
    IntelliJ IDEA简介及简单操作
    eclipse开发创建web项目
    myeclipse/eclipse 配置SSM框架错误之一解决方法
  • 原文地址:https://www.cnblogs.com/lhl66/p/13129995.html
Copyright © 2020-2023  润新知