user2666750
user2666750

Reputation: 602

javascript deep copy using JSON

I have problem with javascript object(array) deep copy. I read many good way to deal with it. And I also know that jQuery has $.extend API to this problem. But my question is: Can I just using JSON stringify and parse method to solve this problem?

Here's my code:

function deepCopy(oldValue) { 
  var newValue
  strValue = JSON.stringify(oldValue)
  return newValue = JSON.parse(strValue)
}

var a = {
  b: 'b',
  c: [1,2,4],
  d: null
}

copy = deepCopy(a)

console.log(a === copy) // false
console.log(a.c === copy.c) // false

PS: I've known that if no all objects are serializable, but the only situation I know is that when the object contains a property which is function. Any other situation?

Upvotes: 32

Views: 45630

Answers (4)

sldk
sldk

Reputation: 374

Nowadays you can use native deep cloning in modern Node and Browser environments:

const value = {
    a: 'a',
    b: 'b',
    foo: {
        "bar": 42
    }
}

const copy = structuredClone(value)

This answer to a similar question provides even more options.

Upvotes: 1

mayank
mayank

Reputation: 1

I think what you looking for is something like this: If you have a really nested object structure then to make a deep copy you can make use of JSON.stringify().

Please see below example:

var obj= {
      'a':1,
      'b':2,
      'c': {
        'd':{
          'e' : 3
        }
      }
    }


var newObj = {...obj};
var lastObj = JSON.parse(JSON.stringify(obj));
obj.c.d.e =19;
console.log('obj '+obj.c.d.e);
console.log('newObj '+obj.c.d.e);
console.log('lastObj'+lastObj.c.d.e); 

Now lastObj is truly detached from obj while if you use ...(spread) operator than also it does not work in really complex objects.

Hope this helps!!

Upvotes: 0

Joseph Larson
Joseph Larson

Reputation: 9068

You can do it that way, but it's problematic for some of the reasons listed above:

  1. I question the performance.

  2. Do you have any non-serializable properties?

  3. And the biggest: your clone is missing type information. Depending upon what you're doing, that could be significant. Did the implementor add methods to the prototype of your original objects? Those are gone. I'm not sure what else you'll lose.

Upvotes: 3

svidgen
svidgen

Reputation: 14302

If your object is "small" and contains exclusively serializable properties, a simple deepCopy hack using JSON serialization should be OK. But, if your object is large, you could run into problems. And if it contains unserializable properties, those'll go missing:

var o = {
 a: 1,
 b: 2,
 sum: function() { return a + b; }
};

var o2 = JSON.parse(JSON.stringify(o));
console.log(o2);

Yields:

Object {a: 1, b: 2}

Interestingly enough, a fair number of deep-copy solutions in C# are similar serialization/deserialization tricks.

Addendum: Not sure what you're hoping for in terms of comparing the objects after the copy. But, for complex objects, you generally need to write your own Compare() and/or Equals() method for an accurate comparison.

Also notable, this sort of copy doesn't preserve type information.

JSON.parse(JSON.stringify(new A())) instanceof A === false

Upvotes: 45

Related Questions