I just discovered the structuredClone() method. It is a native browser function in JavaScript that will perform a deep clone of objects. Let's demo it!
First, create a few classes:
constructor(value1, value2) {
this.nestedValue1 = value1;
this.nestedValue2 = value2;
}
}
I'll start with a class named NestedClass. This class will be nested inside another class, because when deep cloning I want to make sure that nested objects are cloned by value and not by reference. This class has two values in it.
Next, create the outer class:
2 value1;
3 value2;
4 nestedObject1;
5 nestedObject2;
6
7 constructor(value1, value2, value3, value4) {
8 this.value1 = value1;
9 this.value2 = value2;
10 this.nestedObject1 = value3;
11 this.nestedObject2 = value4
12 }
13}
This is a WrapperClass of the NestedClass. It is expected to contain two simple values, and two complex values representing NestedClass instances.
In situations like this, I'm starting to miss TypeScript.
Let's create an object instance:
2let nestedValue2 = resetNestedValue2('nestedClass2Value1', 'nestedClass2Value2');
3let myObject = new WrapperClass('nonNestedValue1', 'nonNestedValue2', nestedValue1, nestedValue2)
Then output the console log:
You should see something like this:
We have nicely typed objects, with the NestedObject values as properties inside the external object.
Now clone:
And output the cloned Object:
This is where I lost my love for the structuredClone() method:
It did not retain the class; instead converting the classes into generic objects. If we had custom methods, or getter and setters inside the original object, then we lost those in the conversion. Bummer!
However, we do have a deep nested clone of the objects, and can change one without changing the other.
2console.log(myObject.nestedObject1 === myClonedMyObject.nestedObject1 ); // expect false
3console.log(myObject.nestedObject2 === myClonedMyObject.nestedObject2 ); // expect false
The Equality check returns false in all cases, even for the two nested properties:
We can change a few simple values to see what happens:
2console.log(myClonedMyObject.value1 ); // expect nonNestedValue1
3console.log(myObject.value1 === myClonedMyObject.value1 ); // expect true
4
5// Change simple value on Object1
6myObject.value1 = 'nonNestedValue1Modified';
7
8console.log(myObject.value1); // expect nonNestedValue1Modified
9console.log(myClonedMyObject.value1 ); // expect nonNestedValue1
10console.log(myObject.value1 === myClonedMyObject.value1 ); // expect false
The simple values are still seen as equal, but we can change one without the other, as proven by the second check:
Since we already know that objects are different, I'm not gonna create a sample for modifying those.