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对象是无法通过这种方式深复制的。
posted @ 2017-05-14 23:59  zhangce  阅读(196)  评论(0编辑  收藏  举报