• javaScript 深层复制


    在工作中遇到了深浅复制的问题,所以详细总结一下:

    深复制和浅复制只针对像 Object, Array 这样的复杂对象的。简单来说,浅复制只复制一层对象的属性,而深复制则递归复制了所有层级。

    var obj = { a:1, arr: [2,3] };
    var shadowObj = shadowCopy(obj);
    
    function shadowCopy(src) {
      var dst = {};
      for (var prop in src) {
        if (src.hasOwnProperty(prop)) {
          dst[prop] = src[prop];
        }
      }
      return dst;
    }

    这是一种典型的浅复制,shadowCopy方法将对象的各个属性进行依次复制,并不会进行递归复制,而 JavaScript 存储对象都是存地址的,所以浅复制会导致 obj.arr 和 shadowObj.arr 指向同一块内存地址。当其中一个变量对指向的值做了修改,另一个变量在调用时数值也就修改了。

    shadowObj.arr[1] = 5;
    obj.arr[1]   // = 5

    下面给出深复制的代码:

    function deepCopy ( obj ) {
             var tmp = {};  
             for ( var k in obj ) {
                tmp[ k ] = obj[ k ]; 
             }
             return tmp;
        }
        //在这个函数中最关键的一步 tmp[ k ] = obj[ k ]
        //所以这里只需要保证 obj[ k ] 这个赋值是一个深度拷贝的对象即可.
        //注意: 函数的目的是得到 obj 的深拷贝副本. 因此递归一下.
    
        function deepCopy ( obj ) {
            var tmp = {}, k;
                for ( k in obj ) {
                    if ( typeof obj[ k ] === 'object' ) {
                        tmp[ k ] = deepCopy( obj[ k ] );
                    } else {
                        tmp[ k ] = obj[ k ];
                    }
                }
                return tmp;
            }
    
            // 如果处理这个对象
            var o3 = {
                name: 'jim',
                scores: [
                    90, 
                    95,
                    85
                ]
            };
    
            // 该代码无法处理数组的情况,做如下改动
            function deepCopy ( obj ) {
                var tmp = obj.length >= 0 ? 
                            obj instanceof Array ? [] : { length: 0 } : 
                            {}, 
                    k;
                for ( k in obj ) {
                    if ( typeof obj[ k ] === 'object' ) {
                        tmp[ k ] = deepCopy( obj[ k ] );
                    } else {
                        tmp[ k ] = obj[ k ];
                    }
                }
                return tmp;
            }

    对于深复制,如果对象比较大,层级也比较多,深复制会带来性能上的问题。在遇到需要采用深复制的场景时,可以考虑有没有其他替代的方案。在实际的应用场景中,也是浅复制更为常用。

    JSON.parse( JSON.stringify(a) )这种方法比较简单,但同时也存在问题

    • 无法复制函数
    • 原型链没了,对象就是object,所属的类没了。这会抛弃对象的constructor,也就是深复制之后,无论这个对象原本的构造函数是什么,在深复制之后都会变成Object。另外诸如RegExp对象是无法通过这种方式深复制的。
    ======================================= END ========================================
  • 相关阅读:
    [HNOI2015]亚瑟王(概率dp)
    [IOI1998]Polygon(区间dp)
    [SCOI2003]字符串折叠(区间dp)
    [BJOI2006]狼抓兔子(网络流)
    [NOIP2017普及组]跳房子(二分,单调队列优化dp)
    洛谷 P2863 [USACO06JAN]牛的舞会The Cow Prom(Tarjan)
    [SCOI2010]股票交易(单调队列优化dp)
    [POJ1821]Fence(单调队列优化dp)
    [Luogu2365]任务安排(斜率优化)
    股神小L
  • 原文地址:https://www.cnblogs.com/zhangceblogs/p/6854549.html
Copyright © 2020-2023  润新知