2

Is there a way to clone a javascript object? Not a DOM element, but an object with a specific constructor. For instance lets say I have a phone number object:

function PhoneNumber(number, type) {
    this.number = number;
    this.type = type;
}

var phoneObj1 = new PhoneNumber('1111111111', 'Home');
var phoneObj2 = //Copy of phoneObj1, but unique so I can set other parameters if necessary.

jQuery solves this problem for me with extend.

var phoneObj2 = $.extend({}, phoneObj1);

But it returns a generic object:

Object{number:'1111111111' type:'Home'}

Instead of with the Phone Number constructor name. I need a way of passing in the original phoneObj1's constructor without actually writing new PhoneNumber() in the extend, because the code this is being used in is used by many different types of Objects so at any given time I don't know the exact constructor that should be used except for the fact that I have an object to reference.

var phoneObj2 = $.extend(new PhoneNumber(), phoneObj1); //I CANNOT do this!

//Maybe something like this?
var phoneObj2 = $.extend(new phoneObj1.constructor.name, phoneObj1); //This throws an error.
ryandlf
  • 27,155
  • 37
  • 106
  • 162
  • 2
    possible duplicate of [What is the most efficient way to clone a JavaScript object?](http://stackoverflow.com/questions/122102/what-is-the-most-efficient-way-to-clone-a-javascript-object) – fyr Jan 11 '12 at 07:38
  • some good answers here http://stackoverflow.com/questions/332422/how-do-i-get-the-name-of-an-objects-type-in-javascript – georg Jan 11 '12 at 07:39
  • agreed with 'fyr'. I would give this a shot as the most straight forward way: Object.create(obj); – dbrin Jan 11 '12 at 07:46

4 Answers4

1

I you only need to support modern version of (45) or (34) you can use the new Object.assign() method.

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. It will return the target object.

Example

var phoneObj2 = Object.assign({}, phoneObj1);
console.log(phoneObj2);

This will take all of the properties in phoneObj1, copy them to the empty object {}, and return the combined object as phoneObj2. The empty {} object and the phoneObj2 variable point to the same object in memory after using the assign method.

For more information checkout the info on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

Eric
  • 6,563
  • 5
  • 42
  • 66
  • @ryandlf , if my answer worked for you can you [vote up](https://stackoverflow.com/help/privileges/vote-up) or [accept](https://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work) it? – Eric Nov 03 '15 at 08:03
1

You could have a method (perhaps called copy()) on each of your different types of objects that either returns the constructor for that type of object or just makes a copy of itself (calling the right constructor, since it knows what kind of object it is). So, you just call the same method on all the objects and it does the work for you.

You could put this functionality in a base class and all each derived class would have to do is set the constructor function and all the rest of the code would be common.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
0

Turns out that

var phoneObj2 = $.extend(new phoneObj1.constructor, phoneObj1);

Does work. I was just cancelling the constructor of phoneObj1 on an unrelated note. So this can be used as an abstract way of cloning an object without specifically writing the actual constructor. I can simply inherit the constructor from the object I am cloning.

ryandlf
  • 27,155
  • 37
  • 106
  • 162
-1

Checkout the full post -> https://jscurious.com/how-to-deep-clone-objects-in-javascript/

const obj = {
      name: 'Amitav', 
      age: 24,
      address: {
          city: 'Bangalore',
          state: 'Karnataka'
      }
};
 
const makeDeepClone = (obj) => {
    let newObject = {};
 
    Object.keys(obj).map(key => {
        if(typeof obj[key] === 'object'){
            newObject[key] = makeDeepClone(obj[key]);
        } else {
            newObject[key] = obj[key];
        }
  });
 
  return newObject;
}
 
const copyObj = makeDeepClone(obj);
console.log(copyObj); 
// {name: "Amitav", age: 24, address: {city: "Bangalore", state: "Karnataka"}}
copyObj.address.state = 'Odisha';
console.log(obj.address.state); // "Karnataka"
console.log(copyObj.address.state); // "Odisha"
TylerH
  • 20,799
  • 66
  • 75
  • 101
am232
  • 1
  • 4