I have two objects inst1, inst2 which are both instances of the same class. If I use
inst2 = JSON.parse(JSON.stringify(inst1));
now if I change values of properties of inst2, values in inst1 do not change. That is great. But sadly methods of inst2 have disappeared. So if I do
inst2.method1();
I get the error "inst2.method1 is not a function"
Is there some way I can copy the values in an instance without destroying methods? (obviously I could laboriously copy each value. I am trying to avoid that because I am lazy.)
I have tried to follow typescript - cloning object but I cannot make it work-
CodePudding user response:
You should use structured cloning, see this answer: How do I correctly clone a JavaScript object?
The reason that your current code isn't working is because you are parsing a stringified json object. Json stringify will remove all of the methods of an object and only stringify the objects values.
CodePudding user response:
Ok, I have played a little since the provided answers are not 100% clear.
If you want to have a shallow copy and copy the methods too, you can use Object.create
.
Again: If your object is simple enough, Object.create
will be sufficient for you
const originalPerson = new Person("John");
originalPerson.address = new Address("Paris", "France");
const newPerson = Object.create(originalPerson);
/// this will be true
const isInstanceOf = newPerson instanceof Person;
//this will change the property of the new person ONLY
newPerson.name = "Peter";
//methods will work
newPerson.someMethod();
//methods will work even on nested objects instances
newPerson.address.anotherMethod();
// BUT if we change the city on any of the instances - will change the address.city of both persons since we have done a shallow copy
newPerson.address.city = "Berlin";
I have created typescript playground (just remove the types) to show it works and the drawback with its usage - link to the playground
Another approach is the class itself to have a clone method and to be responsible for its own cloning logic. An example follows, along with a link to another playground
class Address {
constructor(city, country) {
this.city = city;
this.country = country;
}
clone() {
// no special logic, BUT if the address eveolves this is the place to change the clone behvaiour
return Object.create(this);
}
getAddressDetails() {
return `City: ${this.city} country ${this.country}`;
}
}
class Person {
constructor(name, address) {
this.name = name;
this.address = address;
}
clone() {
const newInstance = Object.create(this);
//clone all other class instances
newInstance.address = this.address.clone();
return newInstance;
}
getPersonDetails() {
//calling internally address.getAddressDetails() ensures that the inner object methods are also cloned
return `This is ${this.name}, I live in ${this.address.getAddressDetails()}`
}
}
const originalAddress = new Address("Paris", "France");
const originalPerson = new Person("John", originalAddress);
const clonedPerson = originalPerson.clone();
clonedPerson.name = "Peter";
clonedPerson.address.city = "Berlin";
clonedPerson.address.country = "Germany";
// Log to console
console.log(`Original person: ${originalPerson.getPersonDetails()}`)
console.log(`Cloned person: ${clonedPerson.getPersonDetails()}`)