Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deep copying array of nested objects in javascript [duplicate]

Tags:

I am trying to deep copy array of nested objects in javascript. My array look like this

var arr = [{name:"adam",age:"21"},     {name:"freddie",age:"35",children:[{name:"mercury",age:"25"}]},     {name:"jim",age:"35",children:[{name:"morrison",age:"25",children:[{name:"some", age:"40"}]}]}     ]; 

I want to make a deep copy of every object inside the array that is i want to create a exact copy of arr into new array which should not have object reference. Depth of array is also unknown that is children array can be upto any level. I have gone through this link Copying of an array of objects to another Array without object reference in javascript(Deep copy) but that did not help me. I googled and found some solutions in jQuery but that did not help me as i dont have knowledge of jQuery.

I also tried implementing it with recursion but that's not working too http://ideone.com/kJi5X3

I want to do it in javascript only without using jQuery or anything. I am new to JavaScript so i may have missed if there is any library or simple method to do this. Please help me to solve this problem. Thanks in advance.

like image 250
user2912611 Avatar asked Mar 05 '15 11:03

user2912611


People also ask

How do you deep copy a nested object?

assign() was the most popular way to deep copy an object. Object. assign() will copy everything into the new object, including any functions. Mutating the copied object also doesn't affect the original object.

What is the most efficient way to deep clone an object in JavaScript?

According to the benchmark test, the fastest way to deep clone an object in javascript is to use lodash deep clone function since Object. assign supports only shallow copy.


1 Answers

You have two main options:

  1. Use JSON.stringify and JSON.parse:

     var copy = JSON.parse(JSON.stringify(original)); 

But I've never liked that. A round-trip through text is inefficient at best, and it won't handle functions or Date, RegExp, undefined, etc. values correctly unless you write a replacer and a reviver.

  1. Use a recursive function, something like this:

var toString = Object.prototype.toString; function deepCopy(obj) {     var rv;      switch (typeof obj) {         case "object":             if (obj === null) {                 // null => null                 rv = null;             } else {                 switch (toString.call(obj)) {                     case "[object Array]":                         // It's an array, create a new array with                         // deep copies of the entries                         rv = obj.map(deepCopy);                         break;                     case "[object Date]":                         // Clone the date                         rv = new Date(obj);                         break;                     case "[object RegExp]":                         // Clone the RegExp                         rv = new RegExp(obj);                         break;                     // ...probably a few others                     default:                         // Some other kind of object, deep-copy its                         // properties into a new object                         rv = Object.keys(obj).reduce(function(prev, key) {                             prev[key] = deepCopy(obj[key]);                             return prev;                         }, {});                         break;                 }             }             break;         default:             // It's a primitive, copy via assignment             rv = obj;             break;     }     return rv; } var a = [1, {foo: "bar"}, ['a', 'b'], new Date()]; snippet.log(JSON.stringify(a)); var b = deepCopy(a); snippet.log(JSON.stringify(b));
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 --> <script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

Note that the above uses ES5 features present on all modern browsers but not some older ones, like IE8. All of the features used above can be polyfilled, however, for older browsers.

That doesn't try to get into handling custom constructor functions or preserving prototypes on objects in the array; doing so makes things dramatically more complicated and impossible to make perfect without a convention for how to call those constructors for a copy operation. You can get close by assigning the same prototype, but that wouldn't account for logic within the constructor function and in particular for functions set up as closures within it.

like image 126
T.J. Crowder Avatar answered Sep 29 '22 04:09

T.J. Crowder