Home Copying array by value in JavaScript

# Copying array by value in JavaScript

Dan
1#
Dan Published in 2011-09-20 13:38:08Z
 When copying an array in JavaScript to another array: var arr1 = ['a','b','c']; var arr2 = arr1; arr2.push('d'); //Now, arr1 = ['a','b','c','d']  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?
Community
2#
 Use this: var newArray = oldArray.slice();  Basically, the slice() operation clones the array and returns the reference to the new array. Also note that: For references, strings and numbers (and not the actual object), slice copies object references into the new array. Both the original and new array refer to the same object. If a referenced object changes, the changes are visible to both the new and original arrays. Primitives such as strings and numbers are immutable so changes to the string or number are impossible.
jondavidjohn
3#
 No jQuery needed... Working Example var arr2 = arr1.slice()  This copys the array from the starting position 0 through the end of the array. It is important to note that it will work as expected for primitive types (string, number, etc.), and to also explain the expected behavior for reference types... If you have an array of Reference types, say of type Object. The array will be copied, but both of the arrays will contain references to the same Object's. So in this case it would seem like the array is copied by reference even though the array is actually copied.
Peter Mortensen
4#
Peter Mortensen Reply to 2015-09-06 11:32:58Z
 If you want to make a new copy of an object or array, you must explicitly copy the properties of the object or the elements of the array, for example: var arr1 = ['a','b','c']; var arr2 = []; for (var i=0; i < arr1.length; i++) { arr2[i] = arr1[i]; }  You can search for more information on Google about immutable primitive values and mutable object references.
Ninjakannon
5#
 An alternative to slice is concat, which can be used in 2 ways. The first of these is perhaps more readable as the intended behaviour is very clear: var array2 = [].concat(array1);  The second method is: var array2 = array1.concat();  Cohen (in the comments) pointed out that this latter method has better performance. The way this works is that the concat method creates a new array consisting of the elements in the object on which it is called followed by the elements of any arrays passed to it as arguments. So when no arguments are passed, it simply copies the array. Lee Penkman, also in the comments, points out that if there's a chance array1 is undefined, you can return an empty array as follows: var array2 = [].concat(array1 || []);  Or, for the second method: var array2 = (array1 || []).concat();  Note that you can also do this with slice: var array2 = (array1 || []).slice();.
Peter Mortensen
6#
Peter Mortensen Reply to 2015-09-06 11:39:02Z
 Some of mentioned methods work well when working with simple data types like number or string, but when the array contains other objects these methods fail. When we try to pass any object from one array to another it is passed as a reference, not the object. Add the following code in your JavaScript file: Object.prototype.clone = function() { var newObj = (this instanceof Array) ? [] : {}; for (i in this) { if (i == 'clone') continue; if (this[i] && typeof this[i] == "object") { newObj[i] = this[i].clone(); } else newObj[i] = this[i] } return newObj; };  And simply use var arr1 = ['val_1','val_2','val_3']; var arr2 = arr1.clone()  It will work.
Zyox
7#
 Here's a variant: var arr1=['a', 'b', 'c']; var arr2=eval(arr1.toSource()); arr2.push('d'); console.log('arr1: '+arr1+'\narr2: '+arr2); /* * arr1: a,b,c * arr2: a,b,c,d */ 
A.Zaben
8#
 Adding to the solution of array.slice(); be aware that if you have multidimensional array sub-arrays will be copied by references. What you can do is to loop and slice() each sub-array individually var arr = [[1,1,1],[2,2,2],[3,3,3]]; var arr2 = arr.slice(); arr2[0][1] = 55; console.log(arr2[0][1]); console.log(arr[0][1]); function arrCpy(arrSrc, arrDis){ for(elm in arrSrc){ arrDis.push(arrSrc[elm].slice()); } } var arr3=[]; arrCpy(arr,arr3); arr3[1][1] = 77; console.log(arr3[1][1]); console.log(arr[1][1]);  same things goes to array of objects, they will be copied by reference, you have to copy them manually
Peter Mortensen
9#
Peter Mortensen Reply to 2015-09-06 11:40:25Z
 This is how I've done it after trying many approaches: var newArray = JSON.parse(JSON.stringify(orgArray));  This will create a new deep copy not related to the first one (not a shallow copy). Also this obviously will not clone events and functions, but the good thing you can do it in one line, and it can be used for any kind of object (arrays, strings, numbers, objects ...)
tfmontague
10#

In Javascript, deep-copy techniques depend 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 has higher 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 lower performance. More surprisingly, $.extend() has higher performance than the JSON.parse(JSON.stringify(myArray)) technique http://jsperf.com/js-deep-copy/15. And for those developers that shy away from third-party libraries (like jQuery), you can use the following custom function; which has higher performance than$.extend, and deep-copies all arrays.

// Warning: In Node.js this solution is problematic;
//   any null elements in the deep copied array will
//   be converted to empty object literals {}.
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;
}


## 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?

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 highest performance.

// Highest performance for deep copying literal values
arr2 = arr1.slice();

// Any of these techniques will deep copy literal values as well,
//   but with lower 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  fiat 11# fiat Reply to 2015-10-29 23:45:26Z  In my particular case I needed to ensure the array remained intact so this worked for me: // Empty array arr1.length = 0; // Add items from source array to target array for (var i = 0; i < arr2.length; i++) { arr1.push(arr2[i]); }  heena Jethva 12# heena Jethva Reply to 2017-02-06 07:13:12Z  Make copy of multidimensional array/object: function deepCopy(obj) { if (Object.prototype.toString.call(obj) === '[object Array]') { var out = [], i = 0, len = obj.length; for ( ; i < len; i++ ) { out[i] = arguments.callee(obj[i]); } return out; } if (typeof obj === 'object') { var out = {}, i; for ( i in obj ) { out[i] = arguments.callee(obj[i]); } return out; } return obj; }  Thanks to James Padolsey for this function. Source: Here heena Jethva 13# heena Jethva Reply to 2017-02-06 07:46:48Z  There's the newly introduced Array.from, but unfortunately, as of the time of this writing it's only supported on recent Firefox versions (32 and higher). It can be simply used as follows: var arr1 = [1, 2, 3]; console.log(Array.from(arr1)); // Logs: [1, 2, 3]  Reference: Here Or Array.prototype.map may be used with an identity function: function identity(param) { return param; } var arr1 = [1, 2, 3], clone = arr1.map(identity);  Reference: Here Peter Mortensen 14# Peter Mortensen Reply to 2015-09-06 11:52:41Z  If you are in an environment of ECMAScript 6, using the Spread Operator you could do it this way: var arr1 = ['a','b','c']; var arr2 = [...arr1]; //copy arr1 arr2.push('d'); console.log(arr1) console.log(arr2)  Luke Femur 15# Luke Femur Reply to 2017-07-05 05:57:45Z  You can use array spreads ... to copy arrays. const itemsCopy = [...items]; Also if want to create a new array with the existing one being part of it: var parts = ['shoulders', 'knees']; var lyrics = ['head', ...parts, 'and', 'toes'];  Array spreads are now supported in all major browsers but if you need older support use typescript or babel and compile to ES5. More info on spreads Boopathi Rajaa 16# Boopathi Rajaa Reply to 2015-12-24 07:14:04Z  From ES2015, var arr2 = [...arr1];  Lewis 17# Lewis Reply to 2016-05-31 06:37:03Z  I personally think Array.from is a more readable solution. By the way, just beware of its browser support. //clone let x = [1,2,3]; let y = Array.from(x); //deep clone let clone = arr => Array.from(arr,item => Array.isArray(item) ? clone(item) : item); let x = [1,[],[[]]]; let y = clone(x);  Alex Tsurika 18# Alex Tsurika Reply to 2017-01-12 19:26:26Z  Using jQuery deep copy could be made as following: var arr2 =$.extend(true, [], arr1); 
Alireza
19#
 As we know in Javascript arrays and objects are by reference, but what ways we can do copy the array without changing the original array later one? Here are few ways to do it: Imagine we have this array in your code: var arr = [1, 2, 3, 4, 5];  1) Looping through the array in a function and return a new array, like this:  function newArr(arr) { var i=0, res = []; while(i
ankur kushwaha
20#
ankur kushwaha Reply to 2017-06-30 19:16:15Z
 You can also use ES6 spread operator to copy Array var arr=[2,3,4,5]; var copyArr=[...arr]; 
 You need to login account before you can post.
Processed in 0.53128 second(s) , Gzip On .