• 关于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>

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

  • 相关阅读:
    css考核点整理(十二)-能描述下你在项目中都用到了哪些符合逐渐增强和优雅降级的理念的技巧吗
    css考核点整理(十一)-响应式开发经验,响应式页面的三种核心技术是什么
    css考核点整理(十)-响应式开发经验,响应式页面的三种核心技术是什么
    css考核点整理(九)-有几种文字替换方式,之间的优缺点
    css考核点整理(八)-在什么情况下通过img引入图片,什么情况用背景图引入?背景属性有哪些
    img标签src路径为空就会出现边框,css怎么去掉
    如何避开JavaScript浮点数计算精度问题(如0.1+0.2!==0.3)
    Table中采用JQuery slideToggle效果的问题
    svg转字体icon
    JS取date的前一天时间
  • 原文地址:https://www.cnblogs.com/lhl66/p/13129995.html
Copyright © 2020-2023  润新知