深拷贝-浅拷贝

浅拷贝

    var obj = {a: 1, b: {c: 2}}
    var obj1 = obj
    var obj2 = shallowCopy(obj);
    function shallowCopy(src) {
        var dst = {};
         for (var prop in src) {
             if (src.hasOwnProperty(prop)) {
                 dst[prop] = src[prop];
              }
          }
         return dst;
    }
    
    var obj3 = Object.assign({}, obj)
    
    obj.a = 2
    obj.b.c = 3
    
    console.log(obj) // {a: 2, b: {c: 3}}
    console.log(obj1) // {a: 2, b: {c: 3}}
    console.log(obj2) // {a: 1, b: {c: 3}}
    console.log(obj3) // {a: 1, b: {c: 3}}

这段代码可以说明赋值得到的对象 obj1 只是将指针改变,其引用的仍然是同一个对象,而浅拷贝得到的的 obj2 则是重新创建了新对象。但是,如果原对象obj中存在另一个对象,则不会对对象做另一次拷贝,而是只复制其变量对象的地址。这是因为浅拷贝只复制一层对象的属性,并不包括对象里面的为引用类型的数据。

对于数组,更长见的浅拷贝方法便是slice(0)concat()

ES6 比较常见的浅拷贝方法便是 Object.assign

深拷贝

通过上面的这些说明,相信你对深拷贝大致了解了是怎样一个东西了:深拷贝是对对象以及对象的所有子对象进行拷贝。那么如何实现这样一个深拷贝呢?

  1. JSON.parse(JSON.stringify(obj))

对于常规的对象,我们可以通过JSON.stringify来讲对象转成一个字符串,然后在用JSON.parse来为其分配另一个存储地址,这样可以解决内存地址指向同一个的问题:

    var obj = {a: {b: 1}}
    var copy = JSON.parse(JSON.stringify(obj))
    
    obj.a.b = 2
    console.log(obj) // {a: {b: 2}}
    console.log(copy) // {a: {b: 1}}

但是 JSON.parse()、JSON.stringify也存在一个问题,JSON.parse()和J SON.stringify()能正确处理的对象只有Number、String、Array等能够被 json 表示的数据结构,因此函数这种不能被 json 表示的类型将不能被正确处理。

    var target = {
        a: 1,
        b: 2,
        hello: function() { 
                console.log("Hello, world!");
        }
    };
    var copy = JSON.parse(JSON.stringify(target));
    console.log(copy);   // {a: 1, b: 2}
    console.log(JSON.stringify(target)); // "{"a":1,"b":2}"
  1. 遍历实现属性复制

既然浅拷贝只能实现非object第一层属性的复制,那么遇到object只需要通过递归实现浅拷贝其中内部的属性即可:

    function extend (source) {
      var target
      if (typeof source === 'object') {
        target = Array.isArray(source) ? [] : {}
        for (var key in source) {
          if (source.hasOwnProperty(key)) {
            if (typeof source[key] !== 'object') {
              target[key] = source[key]
            } else {
              target[key] = extend(source[key])
            }
          }
        }
      } else {
        target = source
      }
      return target
    }
    
    var obj1 = {a: {b: 1}}
    var cpObj1 = extend(obj1)
    obj1.a.b = 2
    console.log(cpObj1) // {a: {b: 1}}
    
    var obj2 = [[1]]
    var cpObj2 = extend(obj2) 
    obj2[0][0] = 2
    console.log(cpObj2) // [[1]]

你可能感兴趣的:(深拷贝-浅拷贝)