Copying and Object in JavaScript

Up until yesterday, I thought the correct way to copy an object in JavaScript is using Object.assign().

let obj = {a: 1, b: 2, c: 3};
let newObj = Object.assign({}, obj);
// assign new value to a in newObj
newObj.a = 4;
// old obj should be unaffected, no reference error
// returns original obj {a: 1, b: 2, c: 3}

A reference error is created when you set one variable equal to another, changes to one can affect another. By assigning properties from our original object we can avoid this issue altogether, right? Apparently not.

You have reference issues with any deep nested properties.

let obj = {a: 1, b: 2, c: {d: 4} };
let newObj = Object.assign({}, obj);
// reassign new value to c.d
newObj.c.d = 5;
// obd obj has been changed with newObj
// returns {a: 1, b: 2, c: {d: 5} }
// what I had expected {a: 1, b: 2, c: {d: 4} }

So there it is, reference errors copying any object with deep nested properties.

Yesterday I was chasing down a strange bug in a react-redux application. Something was changing my redux store even though that particular reducer was never called. What had happened was as I set state in another reducer, I used Object.assign({}, obj) to (I thought) copy an object from another store. In reality, I as I changed an array nested with the copied object, the original object was affected as well.

My example was with an edit work flow, so if a user canceled the edit it would appear that the changes were saved (until the page is refreshed and the store is reset).

I can’t believe in (almost) 2018, with all the improvements made to make programming cleaner, that the best way to copy a JavaScript object is this:

let obj = {a: 1, b: 2, c: {d: 4}};
let newObj = JSON.parse(JSON.stringify(obj));
newObj.c.d = 100// original object c.d is unaffected
// returns {a: 1, b: 2, c: {d: 4}}
// returns {a: 1, b: 2, c: {d: 100}}

But, that is how Mozilla recommends you deep clone an object. They even have a warning section about this shortcoming on Object.assign() in the mdn docs.

I hope this post helps someone else avoid wasting hours as I did.

Written by

software developer at canvas technology

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store