In Javascript, deep-copy techniques depends on the elements in an array.
Let's start there.
Three types of elements
Elements can be: literal values, literal structures, or prototypes.
// Literal values (type1)
var booleanLiteral = true;
var numberLiteral = 1;
var stringLiteral = 'true';
// Literal structures (type2)
var arrayLiteral = [];
var objectLiteral = {};
// Prototypes (type3)
var booleanPrototype = new Bool(true);
var numberPrototype = new Number(1);
var stringPrototype = new String('true');
var arrayPrototype = new Array();
var objectPrototype = new Object(); # or "new function () {}"
From these elements we can create three types of arrays.
// 1) Array of literal-values (boolean, number, string)
var type1 = [true, 1, "true"];
// 2) Array of literal-structures (array, object)
var type2 = [[], {}];
// 3) Array of prototype-objects (function)
var type3 = [function () {}, function () {}];
Deep copy techniques depend on the three array types
Based on the types of elements in the array, we can use various techniques to deep copy.
Array of literal-values (type1)
The myArray.splice(0)
, myArray.slice()
, and myArray.concat()
techniques can be used to deep copy arrays with literal values (boolean, number, and string) only; where Slice is faster in performance than Concat (http://jsperf.com/duplicate-array-slice-vs-concat/3).
Array of literal-values (type1) and literal-structures (type2)
The JSON.parse(JSON.stringify(myArray))
technique can be used to deep copy literal values (boolean, number, string) and literal structures (array, object), but not prototype objects.
All arrays (type1, type2, type3)
The jQuery $.extend(myArray)
technique can be used to deep-copy all array-types. Libraries like Underscore and Lo-dash offer similar deep-copy functions to jQuery $.extend()
, yet have slower performance. More surprisingly, $.extend()
has faster performance than the JSON.parse(JSON.stringify(myArray))
technique http://jsperf.com/js-deep-copy/2.
Summarized into a table:

And for those developers that shy away from third-party libraries (like jQuery), you can use the following custom function; which has faster performance than $.extend, and deep-copies all arrays.
function copy(o) {
var output, v, key;
output = Array.isArray(o) ? [] : {};
for (key in o) {
v = o[key];
output[key] = (typeof v === "object") ? copy(v) : v;
}
return output;
}
Warning: In NodeJS this solution is problematic; any null
elements in the deep copied array will be converted to empty object literals {}
.
So to answer the question...
Question
var arr1 = ['a','b','c'];
var arr2 = arr1;
I realized that arr2 refers to the same array as arr1, rather than a
new, independent array. How can I copy the array to get two
independent arrays?
Answer
Because arr1
is an array of literal values (boolean, number, or string), you can use any deep copy technique discussed above, where slice
has the fastest performance.
// Fastest performance for deep copying literal values
arr2 = arr1.slice();
// Any of these techniques will deep copy literal values as well,
// but with slower performance
arr2 = arr1.splice(0);
arr2 = arr1.concat();
arr2 = JSON.parse(JSON.stringify(arr1));
arr2 = $.extend(true, [], arr1); // jQuery.js needed
arr2 = _.extend(arr1); // Underscore.js needed
arr2 = _.cloneDeep(arr1); // Lo-dash.js needed
arr2 = copy(arr1); // Custom-function needed - as provided above
slice
andsplice
operations and new spread operator andArray.from
have much slower implementation. Look at perfjs.fnfo – Pencroff Sep 16 '16 at 13:32