Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When is it necessary to use the Object.assign() method to copy an instance of an object?

The following is an example scenario I made up for my own practice of this problem. If you want to skip straight to the technical details, please see 'Technical Details' below.

I have a personal project I've been working on to learn JavaScript. Basically, the user can design a shoe by picking available options.

The trick is that the left and right shoe must have the same size, among other properties, but things like color, shoe lace texture, etc. can be independent properties per shoe. (I figured this was a decent way for me to practice object manipulation and inheritance).

The user starts off with designing the right shoe; when the "swap" button is clicked to look at the left shoe, the user currently sees a copy of the right shoe (but inverted). Only on the first swapping of shoes is the left shoe generated and made an exact copy of the right shoe. From then onwards, unique options per shoe orientation are preserved. Then, if the user makes specific changes to that left-shoe model, and then switches to the right shoe, the user is supposed to see the exact same right shoe that they had originally designed before they clicked the "swap" button.

So if their right shoe had red laces, they switch to the left shoe view and make the left shoe have a blue lace, then when switching back to the right shoe the user should see red laces!


Technical Details

When I was writing the code for my main project I was running into trouble with the unique options being perserved. For example, if I made the laces green for the left shoe, the right shoe would always have green laces. Troubleshooting down to the problem was easy because the only time the right shoe was losing it's unique options, such as a red lace, was when I would set the lace color for the left shoe.

console.log("THE RIGHT LACE BEFORE: " + rightShoe.laceId);
leftShoe.laceId = 'green';
console.log("THE RIGHT LACE AFTER: " + rightShoe.laceId);

What would log to the console was:

THE RIGHT LACE BEFORE: red

THE RIGHT LACE AFTER: green

Even though I wasn't changing the rightShoe, it was being changed whenever I changed the leftShoe property.

So I went back to where I first define the leftShoe object, which is when the user clicks "swap" for the first time in the life of the script (My amateur thought was why propagate and fill the leftShoe object if the user possibly never customizes the left shoe? Maybe it's being unnecessarily stingy with data, I don't know). From then onward, I never redefined the leftShoe to be a copy of rightShoe or vice versa. I figured that I was getting hung up by the fact that I was probably doing object referencing and, just like with other languages, I was changing the reference and not the value.

Before coming to SO with my troubles, I wanted to make a JSFiddle to recreate the problem. Being that my project is lengthy (around ~1500 lines, including some THREE.js for graphics), I did my best to emulate the process. And so here it is.

Except the JSFiddle worked exactly as I expected it to! The left model preserved it's unique attribute and data set to that attribute. So, I did a little more digging and read about the Object.assign() method. So in my original project code (not the fiddle), I changed this:

leftShoe = rightShoe;

to this:

leftShoe = Object.assign({}, rightShoe);

As excited as I am to have finally gotten this to work, I am equally amused and perplexed because I don't understand why my JSFiddle didn't need the assign() method but my identical project code did. Thank you.

like image 774
8protons Avatar asked Apr 19 '16 21:04

8protons


People also ask

Why should we use object assign?

assign() which is used to copy the values and properties from one or more source objects to a target object. It invokes getters and setters since it uses both [[Get]] on the source and [[Set]] on the target. It returns the target object which has properties and values copied from the target object.

Does object assign copy?

Using Object.assign() method is used to copy the values of all enumerable own properties from one or more source objects to a target object.

Does object assign do a deep copy?

Object. assign does not copy prototype properties and methods. This method does not create a deep copy of Source Object, it makes a shallow copy of the data. For the properties containing reference or complex data, the reference is copied to the destination object, instead of creating a separate object.


1 Answers

Object.Assign makes a new COPY of the left shoe, including all enumerable OWN properties. When you use leftshoe = rightshoe, you are making a REFERENCE to the left shoe. A reference points to the same object, not a NEW COPY. Thus changing a property of the reference is actually changing the original, as you noted.

like image 168
Timothy Kanski Avatar answered Sep 20 '22 21:09

Timothy Kanski