DEV Community

Discussion on: Learn To Clone Like A Sith Lord

 
bytebodger profile image
Adam Nathaniel Davis • Edited

If you have 1000 elements in array let's say and you update one element, do you clone the whole array (what mean whole is copy of every item)?

This is a straw-man argument that I never made. The original article never said, "You should perform a deep clone on all of your objects - regardless of the size of those objects or the scope of changes that you plan to make." Cloning objects is a tool. Sometimes a hammer is the perfect tool for the job. Sometimes it's ridiculous to use a hammer for a particular job. Showing someone how to clone !== telling someone to always clone.

Finally we can end by quite a lot of rendering issues, and believe me I have been there and have seen a lot of such bugs related to unwanted reference change.

But... this is exactly the point of cloning (where appropriate). Sometimes we need to ensure that we've broken the original references. I don't always clone an object. But when I want to avoid unwanted reference changes, I absolutely reach for cloning.

Thirdly and most importantly fact that we need deep clone means that probably our data structure is wrong, or we pass too much to consumers which should not be aware of the whole.

I get that. You don't want to pass Google to the consumer if the consumer has no need for All Of Google. No argument there. But there are absolutely times when the consumer needs All The Data from an object - but I don't want changes to the consumer's object to be reflected back in the source object.

What I want to say is - when we decompose the data into smaller pieces there is no need for deep copying. The consumer is responsible for it's part is aware of only small piece, and copy this piece in a most flat way.

This isn't "wrong" - but it makes a lot of assumptions about the code.

For one, it makes assumptions about who is the consumer, and who is the provider. For example, I often have to deal with APIs - as a consumer. I can't dictate the shape in which data is provided to me. In this scenario, I am the consumer. For example, an API response that I consume might look something like this:

{
  data: {
    user: {
      title: 'QA',
      name: 'Joe',
      id: '92354',
    },
    supervisor: {
      title: 'Tech Lead',
      name: 'Mary',
      id: '92042',      
    },
    creator: {
      title: 'Developer',
      name: 'Susan',
      id: '82991',      
    },
  }
}
Enter fullscreen mode Exit fullscreen mode

Furthermore, when I'm dealing with API results, it's often helpful (or even necessary) that I maintain a record of the original result that was returned to me. That's why I wouldn't simply pass apiResult.data to downstream consumers. Because if the downstream consumer changes that data directly on the object that was passed to them, I've now lost the record of the API response's "original state".

In that scenario, I could assign every dang value from the API into their own standalone variables, and then pass every dang standalone variable down the line to the next consumer. But that's often a verbose, and unnecessary waste of code.

So, I could pass that down to the next consumer as:

const response = {
  userTitle: apiResult.data.user.title;
  userName: apiResult.data.user.name;
  userId: apiResult.data.user.id;
  supervisorTitle: apiResult.data.user.title;
  supervisorName: apiResult.data.user.name;
  supervisorId: apiResult.data.user.id;
  creatorTitle: apiResult.data.user.title;
  creatorName: apiResult.data.user.name;
  creatorId: apiResult.data.user.id;
};
processResponse(response);
Enter fullscreen mode Exit fullscreen mode

Or... I could just do this:

processResponse(cloneObject(apiResult.data));
Enter fullscreen mode Exit fullscreen mode

And be done with it. And I'll be honest with you. I don't, in any way, feel "bad" about the second approach.

Some comments have been hidden by the post's author - find out more