Copying objects (Advice)

Object references are normally duplicated in preference to the objects themselves.

When you assign the result of a new operation to a variable, you are actually storing a reference to the object. Copying the contents of one variable to another by assignment copies the reference and not the object.

Creating a new object and copying all the top-level properties across from the original is a shallow copy, so called because it only goes one layer into the hierarchy.

If you are able to create a new instance of the object and then recursively copy all the properties across from one to the other, you will have made a deep copy of the object. To do this, you need to traverse all of the branches of the object references, instantiating new copies of any objects you find. This may or may not be possible since some properties may be hidden from view, may be read-only or may not be enumerable and therefore impossible to copy without knowing what they are.

In practice though, any properties you put into the original object from a script are likely to be copyable and you are likely to know enough about your objects to be able to accomplish this at least to the extent that you need.

Comparing two objects may yield a different result depending on whether you are comparing shallow copies or deep copies. Comparing two shallow copies is actually the act of comparing references. If they both refer to the same object, then they must be identical and equal. Comparing deep copies requires a comparison on a property-by-property basis. This may prove that the objects are equal but not identical. A simple compare of the references would prove false.

To compare deep copies, you should implement an object method called isEqualTo() and pass the object that you want to compare. The receiving object can then enumerate its properties and test the passed object for the existence and content of those properties.

You may need to make your deep copy algorithm recursive if you are copying objects that contain references to objects. For example, Arrays of Arrays.

Writing a generalized algorithm is quite difficult if you want it to work across browsers. This is because you need to be able to determine the class of any objects you encounter so that you can perform the right kind of copying on them. This might be easier if you limit the kind of objects you use.

Example code:

   // Copying only an object reference
   myObject1 = new Array("AAA", "BBB", "CCC");
   myObject2 = myObject1;
   
   // Shallow copying (one layer deep)
   myObject1 = new Array("AAA", "BBB", "CCC");
   myObject2 = new Array(myObject1.length);
   for(ii=0; ii<myObject1.length; ii++)
   {
      myObject2[ii] = myObject1[ii];
   }
   
   // Deep copying (knowledge of the internal structure required)
   myItem1   = new Array("A", "B", "C");
   myItem2   = new Array("1", "2", "3", myItem1);
   myObject1 = new Array("X", "Y", "Z", myItem2);
   myObject2 = new Array();
   myObject2[0] = myObject1[0];
   myObject2[1] = myObject1[1];
   myObject2[2] = myObject1[2];
   myObject2[3] = new Array();
   myObject2[3][0] = myObject1[3][0];
   myObject2[3][1] = myObject1[3][1];
   myObject2[3][2] = myObject1[3][2];
   myObject2[3][3] = new Array();
   myObject2[3][3][0] = myObject1[3][3][0];
   myObject2[3][3][1] = myObject1[3][3][1];
   myObject2[3][3][2] = myObject1[3][3][2];

See also:Multi-dimensional arrays