DEV Community

Discussion on: Best way to copy an object in JavaScript?

Collapse
 
foresthoffman profile image
Forest Hoffman • Edited

Well I suppose it depends on how deep the objects are and whether you have control over the organization of the objects. I believe for simple scenarios, you could do something along the following. Dunno if you qualify ES6 as Vanilla JS, so here's some ES5:

function Garage(x, y, cars) {
  // dimensions of the garage in feet, because America :/
  this.area = {
    width: x,
    depth: y,
  }
  this.cars = cars;

  this.copy = function(garage){
    this.area.width = garage.area.width;
    this.area.depth = garage.area.depth;
    for (var i = 0; i < garage.cars.length; i++) {
      this.cars[i] = new Car(garage.cars[i].make, garage.cars[i].model);
    }
  };
}

function Car(make, model) {
  this.make = make;
  this.model = model;
}

(function(){
  var someGarage = new Garage(40.0, 25.0, [
    new Car("Toyota", "Camry"),
    new Car("Toyota", "Prius"),
    new Car("Tesla", "Model 3"),
  ]);
  var otherGarage = new Garage(25.0, 25.0, [
    new Car("Toyota", "Camry"),
  ]);

  // make the second garage a copy of the first, without using references
  otherGarage.copy(someGarage);

  // change the first garage to show that the garages aren't related
  someGarage.cars[2] = null;
  someGarage.area.width++;

  console.log("someGarage: ", someGarage);
  console.log("otherGarage: ", otherGarage);
})();

The output to the console:

someGarage:  {}
    area: Object { width: 41, depth: 25 }
    cars: []
        0: Object { make: "Toyota", model: "Camry" }
        1: Object { make: "Toyota", model: "Prius" }
        2: null
        length: 3
        __proto__: Array []
    copy: function Garage/this.copy()
    __proto__: Object {  }

otherGarage:  {}
    area: Object { width: 40, depth: 25 }
    cars: []
        0: Object { make: "Toyota", model: "Camry" }
        1: Object { make: "Toyota", model: "Prius" }
        2: Object { make: "Tesla", model: "Model 3" }
        length: 3
        __proto__: Array []
    copy: function Garage/this.copy()
    __proto__: Object {  }

Alternatively, if you have to handle dynamic objects of unknown dimensions, you could use a recursive function that uses Object.getOwnPropertyNames and the prototypes (someObject.__proto__) of those properties to handle the generation of fresh Objects for the properties of the destination object.

Hope that answers your question!

Edit: Added console output for the above script.

Collapse
 
ptasker profile image
Peter Tasker

That does indeed look like a good solution if you know the object props.

But JSON.parse( JSON.stringify( obj ) );, though hacky, is much quicker to write!

Collapse
 
foresthoffman profile image
Forest Hoffman

Oh okay. I misunderstood, I thought you were avoiding using that JSON.parse( JSON.stringify( obj ) ); for some reason. Whoops!

Have a good Turkey day, or a good Thursday.