Here, we have a simple variable foo that points to an object containing a member x that points to a number. We can assign this variable foo to another constant variable called bar.
At this point, bar is actually a reference to the same object in memory. If you mutate the property x (bar), foo.x is also changed. To create an actual copy of the variable foo, we can do it manually.
For example, we assign a new object to bar with a property x pointing to foo.x. Now, if you mutate bar.x, foo.x remains unchanged. Doing this manual object creation and property assignment can quickly become cumbersome if the objects are complex.
For example, let's assume that foo contains a property x, that contains a property y, that contains a property z pointing to a number. In order to copy this to bar, you would actually need to create new object with a property x, and a y, and a z, and finally get to copy foo.x.y.z.
Such manual object cloning and creation is error prone, time consuming, and painful. Fortunately, for simple objects, you can create a simple function to do all of this work for you.
We can call this function deep copy. It is a generic function that takes a type t. It takes an object of type t and returns an object of type t. Within the function, we simply stringify the object parsed in to convert it to a string.
Then we convert this JSON string back into an object using JSON.parse. This gives us a new object with the same properties as object O. Instead of this cumbersome work, we can simply deep copy the object foo to create its copy for variable bar. If you go ahead and mutate some property on bar, the variable foo remains unchanged.
Note that since the deep copy function is using JSON.stringify underneath, it will only work for simple objects, and not for objects that cannot be serialized to strings. For example, objects containing functions or cyclic data structures.