Deep Cloning in JS ? Kindly help

Deep Cloning in JS ? Kindly help
0.0 0

#1

Hi, so i was doing something like this from an example -

let user = {
  name: "John",
  sizes: {
    height: 182,
    width: 50
  }
};

Now to clone it i used —

let newUser = {};

for(let prop1 in user) {
    newUser[prop1] = user[prop1];
}

However when i do this

newUser.sizes.width = 52;

It also sets the same value for

user.sizes.width ---> 52 as well

How can i avoid it and keep two values separate , kindly guide …

I know its being referenced but is there a way to break this reference …


#2

This is happening because user.sizes.width is also an object. There is an answer here about it: https://stackoverflow.com/questions/122102/what-is-the-most-efficient-way-to-deep-clone-an-object-in-javascript/5344074#5344074

This aspect of js is quite frustrating to me.

I haven’t tried it yet, but lodash has a ‘deepClone’ function that would seen to solve the problem: https://lodash.com/docs/4.17.4#cloneDeep


#3

If all of your values can be represented in JSON, you can deep clone pretty easily like this:

let newUser = JSON.parse(JSON.stringify(user));

This will first make a JSON string of your object before then parsing the string back to an object. It will work for the object in your example, but if your object has more complex data types that can’t be preserved in a JSON string, it will break.


#4

You could make your function that deep clones an object

const user = {
  name: "John",
  sizes: {
    height: 182,
    width: 50
  }
};

const deepClone = oldObj => {
  let newObj = oldObj;
  if (oldObj && typeof oldObj === 'object') {
    newObj = Object.prototype.toString.call(oldObj) === "[object Array]" ? [] : {};
    Object.keys(oldObj).forEach(key => {
      newObj[key] = deepClone(oldObj[key]);
    });
  }
  return newObj;
}

const newUser = deepClone(user);
newUser.sizes.width = 52;
console.log(user.sizes.width) // displays 50
console.log(newUser.sizes.width) // displays 52

#5

@r1chard5mith , @raddevon - thanks guys but i have no idea about JSON , @randelldawson - thanks a lot for the wonderful reply but 7 months in to trying to learn JS i am not yet at a level to be able to understand advanced code that you have used, thanks for your valuable time …


#6

That is a sweet trick, but feels pretty hacky

If someone else wanted to added a method to the object like the following, things would break

  name: "John",
  sizes: {
    height: 182,
    width: 50
  },
  sayName: function() {
    console.log(`Hi, my name is ${this.name}`)
  }
};

So I’d rather play it safe and go with randell’s recursive method from the start.


#7

Definitely hacky. I use it a lot but only when I know 100% what’s going to be in my object can be serialized as JSON.


#8

You inspired me to write a post going way to deep on three of the ways you can copy a Javascript object including why and when you’d choose various options.

I hope someone finds it helpful. :grinning:


#9

Would Obect.assign() work for you? Used all the time in redux flow.

let user = {
  name: "John",
  sizes: {
    height: 182,
    width: 50
  }
};

let newUsers = Object.assign({}, user, {
  sizes: {
    ...user.sizes,
    width: 52
  }
})

console.log(user.sizes.width, newUsers.sizes.width); //50, 52