0

Couldn't find an answer dealing with cloning instantiated objects in JavaScript. What's the best way to clone an existing instantiated object? E.g.,

function Person() {
}

Person.prototype.setName = function(name) {
    this.name = name;
}

var person = new Person();
person.setName('Charles Xavier');

function cloneInstantiated(instantiatedObject) {
    var clone = ... new Person ... ????

    return clone;
}

var clone = cloneInstantiated(person);

console.log(clone.name); // Charles Xavier

if(clone !== person) {
    console.log('Success! We have cloned Charles Xavier into a different memory address.');
}
5
  • possible duplicate of What is the most efficient way to clone an object? Commented Dec 9, 2014 at 20:23
  • 1
    @svidgen There's a big difference between Object and instantiated object! Commented Dec 9, 2014 at 20:27
  • @TomášZato All objects are "instantiated." If the concern is that the prototype is absent from the new object after using one of the widely used clone() functions, just add the prototype to the new object after the basic clone(). If the OP's concern is that his clone-method-of-choice doesn't also copy instance methods ... it's simple enough to loop and/or recurse through and add them. Commented Dec 9, 2014 at 20:35
  • Often it's quite important that clone instanceof Person returns true. I don't see a point in "adding the prototype later" if you can instantiate object using new and then copy properties. Commented Dec 9, 2014 at 20:40
  • is o2=Object.create(o) enough for your app? Commented Dec 9, 2014 at 23:14

2 Answers 2

2

There's no native or universal way as far as I know. I prefer to write .clone method for my pseudo classes and use it:

Person.prototype.clone = function() {
    var clone = new Person()
    clone.name = this.name;
}

You could loop through own properties of the object to clone them while not copying stuff inherited from other objects:

for(var i in this) {
   if(this.hasOwnProperty(i)) {
       clone[i] = this[i];
   }
}

This will copy everything that was added to your object after instantiating (eg. won't copy the prototype properties which were already added by calling new Person.

Object.getPrototypeOf

thanks to Bergi
This method allows you to retrieve the prototype of any object. So instead of new Name you can use:

var clone = Object.create(Object.getPrototypeOf(this))

That's an universal solution which can save you lot of work. You must then proceed with copying own properties using for(var i in ...).

Object.create (supported since node V8) (MDN)

Finally, you could create a person that inherits from the original object:

var clone = Object.create(this);

That can be useful in special cases, but normally I wouldn't recommend it.

.toSource (Node.js module) (MDN)

It's also interesting to know that you can (in certain browsers firefox only) override method .toSource which is defined for all objects, even the native ones:

toSource method

In certain cases, you might want to do:

Person.prototype.toSource = function() {
    //Assuming name can be given in constructor
    return "new Person("+this.name.toSource()+")";
}

Further reading

Aside from the linked docs, I found this nice article about javascript object inheritance:

Sign up to request clarification or add additional context in comments.

5 Comments

I'd recomment to use var clone = Object.create(Object.getPrototypeOf(this))
If you get the prototype you don't copy the objects own properties. However your's is a good way to create object of the same instance without typing the name directly. +1 :)
I thought that was the initalisation code for the loop over the own properties in the snippet right above?
Yeah. As I say, your's a good idea. I just wasn't sure you realise that loop is still necesary. I'll try to add your idea to my answer. Thank you.
@Kirk Wasn't my answer sufficient? I've spent a lot of time with it and now it seems you didn't even read it.
0

This works perfectly... Fiddle

function Person() {
}

Person.prototype.setName = function(name) {
    this.name = name;
}

var person = new Person();
person.setName('Charles Xavier');

function cloneInstantiated(instantiatedObject) {
    var clone = {};
    for (key in instantiatedObject) {
        clone[key] = instantiatedObject[key];
    }
    return clone;
}

var clone = cloneInstantiated(person);

console.log(clone.name); // Charles Xavier

if(clone !== person) {
    console.log('Success! We have cloned Charles Xavier into a different memory address.');
}

2 Comments

You've got uninitialised global variable in your code (key). Looping through all keys is really not necessary, usually you just need to copy the topmost layer of inheritance.
What if one of the variables on the instance had captured a reference to the other object, or if a function was explicitly bound for instance? While it works for this specific case, this doesn't work as a generic solution.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.