Written by 11:05 Basics of JavaScript, Languages & Coding

Javascrtipt Deep Copy

In this article, we will discuss how to copy and deep copy javascript objects.

Simple copying of a javascript object

The following function copies all properties of an existing object. It takes an object as an argument and returns a new copy of that object.

function extendCopy(p) {
    var c = {};
    for (var i in p) {
        c[i] = p[i];
    }
    c.uber = p;
    return c;
}

It is a very simple and widely used pattern. Firebug provides the extend() function that uses this approach. Some popular javascript libraries like jQuery and Prototype utilized this pattern in earlier versions.

The same function in action:

var shape = {
    name: 'shape',
    toString: function () { return this.name; }
}

To create a new copy of the object, we can call the extendCopy() function that returns a new object. Then you can add additional properties to the new object.

var twoD = extendCopy(shape);
twoD.name = '2D shape';
twoD.toString = function () {
    return this.uber.toString() + ', ' +
    this.name;
};

A square object that inherits the 2D shape object:

var sqare = extendCopy(twoD);
sqare.name = 'Square';
sqare.getArea = function () { return this.width * this.height }

Using the square:
>>> square.width = 2; square.height = 3; square.getArea();
6
>>> square.toString();
“shape, 2D shape, Square”

One major disadvantage of this method is that you have to manually define values for the object properties, instead just passing them to a constructor. This issue may be resolved with help of the init() function that acts as a constructor and accepts initialization parameters.

Deep Copy

The extendCopy() function creates a shallow copy of an object. As you may know, while copying objects, you only copying pointers to the location in memory where the object is stored. Any modifications in a copy will impact the original object. The deep copy technique allows avoiding this effect.

The deep copy works similar to the shallow copy. You need to iterate through a collection of properties and copy them one-by-one. When you meet a property that points to an object, you need to invoke the deepCopy() again:

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

Create an object with arrays and a sub-object as properties:

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

Now we can create a deep copy and a shallow copy.

>>> var deepC = deepCopy(parent);
>>> var shallowC = extendCopy(parent);
>>> deepC.numbers.push(4,5,6);
6

>>> deepC.numbers
[1, 2, 3, 4, 5, 6]

>>> parent.numbers
[1, 2, 3]

>>> shallowC.numbers.push(10)
4

>>> shallowC.numbers
[1, 2, 3, 10]
>>> parent.numbers[1, 2, 3, 10]
>>> deepC.numbers
[1, 2, 3, 4, 5, 6]

As you can see, when you update a deep copy the original is not affected. The latest versions of jQuery utilize this approach.

Additional information

How to Deep clone in javascript

What is the most efficient way to clone an object?

Most elegant way to clone a JavaScript object

Tags: Last modified: September 23, 2021
Close