Copy of JavaScript objets: reference, avatar and double

Depending on how we assign an object to a variable, we get a reference to the same object, or an avatar, or a separate copy.

Do not know what kind of alter ego we are dealing can cause headache trying to understand how the program behaves...
We will consider each case with examples of the behavior.

The initial object is a simple pair of coordinates called "Point":

var Point = {
"x" : 10,
"y" : 10

Reference and assignment

When an object is assigned to a new variable a new reference to the object is obtained. That variable is just a new name for the same object. If you change the contents of the variable, the original object is modified, and vice versa.

var p = Point
p.x = 20

Point.y = 20

If we change x in the copy, this changes as x in the original, and if we change it in the original, it changes in the copy also: p and Point are definitively two references to the same object.

Avatar with Object.create

This method added to ECMAScript 6 produces a copy of an object. But as we will verify, it's actually an avatar: when the original object is modified, this also changes the copy!

var avatar = Object.create(Point)
Point.y = 63

The value 63 assigned to y in the original object is assigned to y in the copy.

But if we changes the copy, does it change the original too?

avatar.x = 250

This is not the case, the x property was worth 20 before the operation and retains this value.

And if we change x in avatar then we change the same property in the original?

avatar.x = 250
Point.x = 400

The avatar object this time is not affected by the modification of the original.

So, we can create authentic avatars in JavaScript, but these avatars earn their independence when modified!

Separate instance with new

We may want to also use objects as models, but we do not want the copies modified with the original. Then a function must be used instead, which is also an object in JavaScript.

function FPoint() {
  this.x = 5
  this.y = 5
var inst = new FPoint()
FPoint.x = 500
document.write("inst.x = " + inst.x)
document.write("FPoint.x = " + FPoint.x)

We see that attributes of the instance are not changed with the model.

What is the value of the attribute y?

document.write("FPoint.y = " + FPoint.y)

The result is undefined. The attribute value can not be displayed. The value of x therefore is not the value of the attribute of the function, but rather that an x ​​attribute that is added to the variable FPoint which had been assigned the function's body!
To verify this, we create a new instance after assigning x.

var inst2 = new FPoint()
document.write("inst2.x = " + inst2.x)

The value of x is always that of the original definition.
In conclusion, the body of a function can be a model to create objects but does not behave like an object.

However, we can dynamically add attributes to the original as prototypes, then they will be part of the copies, even if instances are declared before these attributes are defined.

FPoint.prototype.z = 333

In this case, the copy behaves as a new avatar of the original object, while if one adds attributes without making prototypes, this does not affect instances, copies are independent.

Using a constructor

If we define an object as a function, it is also possible to pass parameters. In this case, the copy is said to be a class instance and works as such.

var FPoint2 = function(nx) {
  this.x = nx
  this.y = 10

The reference to x in the instance must return 50, while the reference to x in FPoint2 would be undefined because it behaves as a function.

var FPoint2 = function(nx) {
  this.x = nx
  this.y = 10
var fp2 = new FPoint2(50)
document.write("fp2.x = " + fp2.x)

FPoint2's attributes may only be obtained by creating an instance.

Copying a simple object

To duplicate a simple object with no constructor and get a separate, independent copy, one trick is to use JSON.

var Point2 = {
  x: 10,
  y: 10

var p2 = JSON.parse(JSON.stringify(Point2))
document.write("p2.x = " + p2.x)
document.write("p2.y = " + p2.y)

The original object is changed:

Point2.x = 999
document.write("Point2.x = " + Point2.x)
document.write("p2.x = " + p2.x)

We change now the copy:

p2.x = 888
document.write("Point2.x = " + Point2.x)

In both cases, the change affects only the original object and not a copy as unlike the avatar, or or only the copy and not the original unlike a reference.
If the object is is a list of keys-values without embedded object, a simple loop also allows copying:

var pmap = {};
for(var k in Point2) { pmap[k] = Point2[k] };
document.write("pmap.x = " + pmap.x)
document.write("pmap.y = " + pmap.y)

These two solutions are suitable when performance is not crucial, otherwise defining the object as a function is faster.

See also:

© October 22, 2015