How to copy/clone arrays in javascript
© https://commons.wikimedia.org

How to copy/clone arrays in javascript

Avoid pitfalls when copying arrays - shallow/deep

ByMario Kandut

honey pot logo

Europe’s developer-focused job platform

Let companies apply to you

Developer-focused, salary and tech stack upfront.

Just one profile, no job applications!

There are plenty of ways to copy an array in Javascript, they vary in execution speed and limitations regarding data types.

If you think, Why just can't I assign the array to the new array?. Well, let me explain a bit. 🤓

💰 The Pragmatic Programmer: journey to mastery. 💰 One of the best books in software development, sold over 200,000 times.

Arrays are reference values (in javascript).

This means, when you try to copy it with const newArray = oldArray, it will copy the reference to the original array and not copy the values.

const beers = ['🍺', '🍺', '🍺'];

const beersCopy = beers;

console.log(beers === beersCopy);
// The console output will be true, because it's pointing to the exact value in memory.

This means that arrays in javascript are MUTABLE. Please keep that in mind, when working with arrays especially in the context of Redux or MobX.

Shallow Copy Arrays

When copying or cloning arrays the data type of the value is key to decide what method can be used.

If your array only contains primitive immutables values (numbers, booleans, strings, etc.), you can use the following methods.

  • .push
  • ... (spread)
  • .slice
  • Array.from
  • _.clone (lodash)

.push()

A classic array method and the most obvious approach, basically looping over the original array and using the push() method to push elements from the original in the new array.

We simply loop over the original array and push each element to the new array.

const arr = [1, 2, 3];
const newArr = [];
for (let i = 0; i < arr.length; i++) {
  newArr.push(arr[i]);
}

... (spread)

The spread operator is one of the fastest methods and was introduced with ES6. It's clean and simple and a native method (sorry lodash).

const arr = [1, 2, 3];
const newArr = [...arr];

.slice()

The slice() method returns a shallow copy of a portion of an array into a new array object selected from start to end arr.slice([start[, end]]). The original array will not be modified. This is the fastest way to copy an array.

const arr = [1, 2, 3];
const newArr = arr.slice();

Array.from

The Array.from() static method creates a new, shallow-copied Array instance from an array-like or iterable object (Map or Set).

It also takes a optional mapping function as the second parameter Array.from(arrayLike [, mapFn [, thisArg]]).

const arr = [1, 2, 3];
const newArr = Array.from(arr);

_.clone()

The _.clone(value) method from lodash creates a shallow clone of value. It performs well and if you use lodash already in your application it is a viable option.

// import lodash
const _ = require('lodash');

const arr = [1, 2, 3];
const newArr = _.clone(arr);

Deep Copy Arrays

All methods above create shallow copies of arrays. If you have objects as array items, and you try to make a shallow copy, the actual array will be copied, BUT the underlying objects will be passed by reference to the new array.

Let's have a look at this issue with a code example.

const arr = [
  {
    name: 'mario',
    food: 'pizza',
  },
  {
    name: 'luigi',
    food: 'spaghetti',
  },
];

const arrCopy = [...arr];

console.log(arr === arrCopy);
// This will return false, because the array has been copied (shallow copy), new reference in memory.

console.log(arr[0] === arrCopy[0]);
// This will return true, because the reference points to the same place in memory.

There are several methods to create a deep clone.

  • jQuery.extend()
  • _.clonedeep()
  • JSON (stringify/parse)

jQuery.extend()

If you still use jQuery in your project, you can use the extend method from jQuery.

const arr = [
  {
    name: 'mario',
    food: 'pizza',
  },
  {
    name: 'luigi',
    food: 'spaghetti',
  },
];
const arrCopy = jQuery.extend(true, [], arr);

console.log(arr === arrCopy);
// This will return false, because the array has been copied (new reference in memory).

console.log(arr[0] === arrCopy[0]);
// This will return false, because the reference points to a new one in memory.

_.cloneDeep()

The method _.cloneDeep(value) from Lodash does exactly the same thing as _.clone(), except that it recursively clones everything in the array.

const arr = [
  {
    name: 'mario',
    food: 'pizza',
  },
  {
    name: 'luigi',
    food: 'spaghetti',
  },
];

// import lodash
const _ = require('lodash');

const arrCopy = _.cloneDeep(arr);

console.log(arr === arrCopy);
// This will return false, because the array has been copied (new reference in memory).

console.log(arr[0] === arrCopy[0]);
// This will return false, because the reference points to a new one in memory.

JSON methods

JavaScript provides native methods for serialization and deserialization, basically to convert most data types to a JSON string, and then a valid JSON string to an object.

It can be used like this:

const arr = [
  {
    name: 'mario',
    food: 'pizza',
  },
  {
    name: 'luigi',
    food: 'spaghetti',
  },
];

const arrCopy = JSON.parse(JSON.stringify(arr));

console.log(arr === arrCopy);
// This will return false, because the array has been copied (new reference in memory).

console.log(arr[0] === arrCopy[0]);
// This will return false, because the reference points to a new one in memory.

There are some advantages and disadvantages, when using this approach. An advantage is that it doesn't require a third-party library like Lodash. The disadvantage is that the provided array data needs be serializable and the serializing and deserializing via JSON takes some time, hence this is not the fastest approach.

Thanks for reading and if you have any questions, use the comment function or send me a message @mariokandut.

References (and Big thanks): MDN. Resources for developers, by developers., ScottWRobinson, Samantha,

If you want to know more about Javascript, have a look at these Javascript Tutorials.

Scroll to top ↑