Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript cloning a "class" instance [duplicate]

I have a class that goes like this:

function Element(){
    this.changes = {};
}

Now I have an instance of this "Class" like so, el = new Element(). These instances are stored in an array, like elements.push(el).

This array of elements is now stored in an object, which is then pushed in an array, states.

Now there are cases where I need a copy of one of the elements, so I would need to do something like, var cloned = $.extend(true, {}, states[0]). Here I assumed that we are cloning the first state.

The problem now is that what I get, the state[1].elements[0] is still pointing to the original instance. Thus any changes I am making to the cloned object, are changing the original too.

It's frustrating to be stuck on such a trivial problem...

Here is a fiddle I created to test it out: http://jsfiddle.net/E6wLW/

like image 651
Amit Avatar asked Dec 09 '11 12:12

Amit


People also ask

How do you duplicate an object in JavaScript?

var clone = Object. assign({}, obj); The Object. assign() method is used to copy the values of all enumerable own properties from one or more source objects to a target object.

What is copy constructor in JavaScript?

A copy constructor is a constructor that uses another instance of the current class to set up the current instance. Copy constructors are popular in static languages such as C++ and Java, where you can provide multiple versions of a constructor via static overloading.


2 Answers

$.extend is only cloning plain objects. If the object has a constructor then it is not cloned, but just copied.

From the $.extend source:

if ( jQuery.isPlainObject(copy) /* ... */) {
  // do the recursive $.extend call and clone the object                
} else if ( copy !== undefined ) {
  target[ name ] = copy;
  // ^^^^^ just copy
}

So $.extend() will call isPlainObject(el) which will return false, because el has an constructor and instead of cloning the el is copied. So states[1].elements[0] is the same object as states[0].elements[0] because it was not cloned.

If we modify your example from:

function Element(){
  this.changes = {};
}
var el = new Element();    // $.isPlainObject(el); <- false
// ...

into:

var el = { changes: {} };  // $.isPlainObject(el); <- true
// ...

It will clone the el properly. See it HERE.

like image 108
kubetz Avatar answered Oct 04 '22 02:10

kubetz


You can use http://documentcloud.github.com/underscore/#clone to clone object, like:

var cloned = _.clone(states[0]);
like image 36
Wojciech Bednarski Avatar answered Oct 04 '22 04:10

Wojciech Bednarski