Skip to content

Instantly share code, notes, and snippets.

@chrisbradshaw
Created August 4, 2018 15:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chrisbradshaw/1b4c6d7a74913aafc5891b656f3a474f to your computer and use it in GitHub Desktop.
Save chrisbradshaw/1b4c6d7a74913aafc5891b656f3a474f to your computer and use it in GitHub Desktop.
<iframe src="https://giphy.com/embed/3ohzdQhmr2YrxHT45y" width="480" height="480" frameBorder="0" class="giphy-embed" allowFullScreen></iframe>

via GIPHY

Attack of the Clones: When to use JavaScript Object.assign vs spread operator

Traditionally making a clone of an object in JavaScript has not been simple, nor straightforward. You will run into the problem of erroneously picking up attributes from the object's prototype that should be left in the prototype and not copied to the new instance.

However, the ES6 updates added a new JavaScript feature Object.assign(), which simplifies the process.

In this post, I will outline the following information about Object.assign()

  • When to use
  • How to use
  • Limitations
  • Alternatives
  • Object.assign() in Redux

When to use Object.assign()

We have the following Object, and want to clone it:

Our Object

How to use

To clone, simply type:

https://gist.github.com/4d172783ccb1da01e4011e0fa9d33fc1

However, PROCEED WITH CAUTION.

<iframe src="https://giphy.com/embed/3ohrylo2puV7phiwso" width="480" height="270" frameBorder="0" class="giphy-embed" allowFullScreen></iframe>

via GIPHY

This is only a "Shallow" clone. Let me demonstrate what I mean.

Limitations

Let's reassign the value of "c" to the integer 3004, on our new shallowClone object. Should be simple enough:

https://gist.github.com/d09daedd8101b6de4f93e421e710d17a

Now, lets console.log the new value of c on shallowObject, and the value of c on our original object, obj.

https://gist.github.com/5eb2d8452c58f00943649a17f013fb65

Wait..

<iframe src="https://giphy.com/embed/l2JhEYWETxE0h4uxq" width="480" height="270" frameBorder="0" class="giphy-embed" allowFullScreen></iframe>

via GIPHY

Changing the value of c on shallowObject, also modified the value of c on our original object! This is what is meant by a shallow copy. Rather than making a complete clone, this "shallow" clone merely provides reference to values beyond one level deep - it is *NOT* a true clone.

Alternatives

So by now you are probably wondering, "Chris, what are some possibly alternatives to Object.assign()? The syntax is absolutely phenomenal, but sometimes I need a deeper clone than simply one level deep."

Don't worry. I got you.

<iframe src="https://giphy.com/embed/l3fQgjVoyZ1I4EyOs" width="480" height="480" frameBorder="0" class="giphy-embed" allowFullScreen></iframe>

via GIPHY

There are a few possible solutions to creating a deep clone in JavaScript:
  1. JSON.stringify
  2. Complicated solution with recursion - more performant, especially relevant for large objects
  3. jQuery extend - not recommended for performance issues

In this post, I will be demonstrating how using JSON.stringify solves our problem. Two other options are outlined in this excellent Stack Overflow post.

To quickly summarize, the other possibilities are a more complicated solution involving recursion, which I would recommend for larger objects, and to use JQuery which I would not recommend because it is less performant then the solution I am about to propose:

Our New Object

Above you can see our new object (same as our old object, with a new name). We then create a deep clone by converting the object to a string, and then parsing it back to JSON. Let's test if it works by assigning a new value to c on the jasonClone:

https://gist.github.com/beb5ea963e546e75b8c12e267f433a00

Now we can check impact using console.log. Drumroll please..

<iframe src="https://giphy.com/embed/ogGmxeqA8L3sA" width="480" height="258" frameBorder="0" class="giphy-embed" allowFullScreen></iframe>

via GIPHY

https://gist.github.com/10d5904dbed41079aa9ac7d23a48a5ca

Voila! As you can see we have sucessfully deep cloned newObj. The c value on jasonClone updates while the c value on newObj remains the same

Object.assign() in Redux

In this wrap up, I wanted to touch on my most common use case of Object.assign(). One of the core tenets of Redux is to never mutate state, you'll often find yourself using Object.assign() to create copies of objects with new or updated values. Especially as you are writing your reducer functions.

While this is an effective approach, note that utilizing the new object spread syntax to copy enumerable properties from one object to another is more succinct and will result in more readable code, but still requires a babel plugin (babel-plugin-transform-object-rest-spread) as of the writing of this blog post (interestingly, this plugin is a polyfill for Object.assign()).

Sources:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

https://redux.js.org/recipes/usingobjectspreadoperator

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment