Deep copy

The extendCopy() function discussed previously creates what is called a shallow copy of an object, just like extend2() before that. The opposite of a shallow copy would be, naturally, a deep copy. As discussed previously (in the Heads-up when copying by reference section of this chapter), when you copy objects, you only copy pointers to the location in memory where the object is stored. This is what happens in a shallow copy. If you modify an object in the copy, you also modify the original. The deep copy avoids this problem.

The deep copy is implemented in the same way as the shallow copy-you loop through the properties and copy them one by one. However, when you encounter a property that points to an object, you call the deepcopy function again:

    function deepCopy(p, c) { 
      c = c || {}; 
      for (var i in p) { 
        if (p.hasOwnProperty(i)) { 
          if (typeof p[i] === 'object') { 
            c[i] = Array.isArray(p[i]) ? [] : {}; 
    deepCopy(p[i], c[i]); 
          } else { 
            c[i] = p[i]; 
          } 
        } 
      } 
      return c; 
    } 

Let's create an object that has arrays and a subobject as properties:

    var parent = { 
      numbers: [1, 2, 3], 
      letters: ['a', 'b', 'c'], 
      obj: { 
        prop: 1 
      }, 
      bool: true 
    }; 

Let's test this by creating a deep copy and a shallow copy. Unlike the shallow copy, when you update the numbers property of a deep copy, the original is not affected:

    >var mydeep = deepCopy(parent); 
    >var myshallow = extendCopy(parent); 
    >mydeep.numbers.push(4,5,6); 
    6 
    >mydeep.numbers; 
    [1, 2, 3, 4, 5, 6] 
    >parent.numbers; 
    [1, 2, 3] 
    >myshallow.numbers.push(10); 
    4 
    >myshallow.numbers; 
    [1, 2, 3, 10] 
    >parent.numbers; 
    [1, 2, 3, 10] 
    >mydeep.numbers; 
    [1, 2, 3, 4, 5, 6] 

Two side notes about the deepCopy() function: