Deep copying array of nested objects in javascript [duplicate]
You have two main options:
Use
JSON.stringify
andJSON.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
Date
,RegExp
,undefined
, etc. values correctly unless you write a replacer and a reviver.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.