How to copy array by value in JavaScript?

Use this:

let oldArray = [1, 2, 3, 4, 5];

let newArray = oldArray.slice();

console.log({newArray});

Basically, the slice() operation clones the array and returns a reference to a 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.

How to copy an array by value in JavaScript?

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)
const booleanLiteral = true;
const numberLiteral = 1;
const stringLiteral = 'true';

// Literal structures (type2)
const arrayLiteral = [];
const objectLiteral = {};

// Prototypes (type3)
const booleanPrototype = new Bool(true);
const numberPrototype = new Number(1);
const stringPrototype = new String('true');
const arrayPrototype = new Array();
const objectPrototype = new Object(); // or `new function () {}

From these elements, we can create three types of arrays.

// 1) Array of literal-values (boolean, number, string) 
const type1 = [ true, 1, "true" ];

// 2) Array of literal-structures (array, object)
const type2 = [ [], {} ];

// 3) Array of prototype-objects (function)
const 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.

Deep copy techniques

Javascript deep copy techniques by element types
  • Array of literal-values (type1)
    The [ ...myArray ]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 the Spread operator [...myArray ] has the best performance.
  • 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 Lo-dash cloneDeep(myArray) or jQuery extend(true, [], myArray) techniques can be used to deep-copy all array-types. Where the Lodash cloneDeep() technique has the highest performance.
    • And for those who avoid third-party libraries, the custom function below will deep-copy all array-types, with lower performance than cloneDeep() and higher performance than extend(true).
function copy(aObject) {
  // Prevent undefined objects
  // if (!aObject) return aObject;

  let bObject = Array.isArray(aObject) ? [] : {};

  let value;
  for (const key in aObject) {

    // Prevent self-references to parent object
    // if (Object.is(aObject[key], aObject)) continue;
    
    value = aObject[key];

    bObject[key] = (typeof value === "object") ? copy(value) : value;
  }

  return bObject;
}

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 the spread operator ... has the highest performance.

arr2 = [...arr1];
arr2 = arr1.slice();
arr2 = arr1.splice(0);
arr2 = arr1.concat();
arr2 = JSON.parse(JSON.stringify(arr1));
arr2 = copy(arr1); // Custom function needed, and provided above
arr2 = _.cloneDeep(arr1); // Lo-dash.js needed
arr2 = jQuery.extend(true, [], arr1); // jQuery.js needed

Alternative solution

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.

How to copy an array by value without using jQuery?

No jQuery is needed… Working Example

var arr2 = arr1.slice()

This copies 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.

Answer #4:

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 …)

Answer #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 slicevar array2 = (array1 || []).slice();.

Answer #6:

Important!

Most of answers here works for particular cases.

If you don’t care about deep/nested objects and props use (ES6):

let clonedArray = [...array]

but if you want to do deep clone use this instead:

let cloneArray = JSON.parse(JSON.stringify(array))*

*functions won’t be preserved (serialized) while using stringify, you will get result without them.


For lodash users:

let clonedArray = _.clone(array)

and

let clonedArray = _.cloneDeep(array)

How to copy array by value in JavaScript?

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.

Answer #7:

Primitive values are always pass by its value (copied). Compound values however are passed by reference.

So how do we copy this arr?

let arr = [1,2,3,4,5];

Copy an Array in ES6

let arrCopy = [...arr]; 

Copy n Array in ES5

let arrCopy = arr.slice(); 
let arrCopy = [].concat(arr);

Why `let arrCopy = arr` is not passing by value?

Passing one variable to another on Compound values such as Object/Array behave differently. Using assign operator on copy and values we pass a reference to an object. This is why the value of both arrays is changing when removing/adding arr elements.

Exceptions:

arrCopy[1] = 'adding new value this way will unreference';

When you assign a new value to the variable, you are changing the reference itself and it doesn’t affect the original Object/Array.

Hope you learned something from this post. The primary source of this article is StackOverflow.

Follow Programming Articles for more!

About ᴾᴿᴼᵍʳᵃᵐᵐᵉʳ

Linux and Python enthusiast, in love with open source since 2014, Writer at programming-articles.com, India.

View all posts by ᴾᴿᴼᵍʳᵃᵐᵐᵉʳ →