32

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?

Cœur
  • 37,241
  • 25
  • 195
  • 267
user2666750
  • 582
  • 1
  • 7
  • 11
  • Not all objects are serializable as JSON. Even ones that are, it seems inefficent to turn them into a string and then parse the string. But it should work just fine. Only issue is old versions of IE where you need a polyfill. – Tim Seguine Dec 18 '13 at 15:41
  • check here http://msdn.microsoft.com/en-us/library/ie/cc836466(v=vs.94).aspx – Anand Jha Dec 18 '13 at 15:44
  • Thanks! I only know an object isn't serializable if this object contains property which is a function. But if other situation that the object is not serializable? – user2666750 Dec 19 '13 at 04:27
  • On the other hand, is it really inefficent to deep copy object using JSON compared to normal way? – user2666750 Dec 19 '13 at 04:29
  • Your deep copy works. And [object comparison](https://stackoverflow.com/questions/7837456/how-to-compare-arrays-in-javascript) is working as it should. All is well! – Robert Christian Jul 25 '17 at 06:30

3 Answers3

45

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
svidgen
  • 13,744
  • 4
  • 33
  • 58
  • 2
    This is a nice solution for quick debugging in Chrome's console, since Chrome will always display the final state of the object, instead of the one how it was when the console.log function got called. – Daniel F Sep 25 '14 at 15:17
3

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.

Joseph Larson
  • 8,530
  • 1
  • 19
  • 36
0

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!!

mayank
  • 1
  • 1