How can I make a copy of an array without reference?

Asked

Viewed 7,972 times

14

I would like to know how to make a copy of an array without reference.

Example of what I would like to do:

var a = [1,2,3,4];
var b = a;

a[0] = 3;
b[0] = "nao me copie!"
console.log(a[0]) //mostrar 3
console.log(b[0]) //mostrar frase nao me copie!

Thank you!

4 answers

13


You can use the method slice without passing arguments to a blank copy (source), or something like the angular.copy for a deep copy:

var b = a.slice();
// ou
var b = angular.copy(a);

In your example above it makes no difference to use one or the other, but if the array elements were complex objects, the shallow copy would simply copy the references to the elements, while the deep copy would also copy the elements themselves (recursively):

var a = [true, 10, "teste", [1,2,3], { outro:"objeto" }];

var b1 = a.slice();       // cópia rasa
var b2 = angular.copy(a); // cópia profunda

// Modificando "a"
a[0] = false;         // Não afeta b1 nem b2
a[1] = 20;            // Idem
a[2] = "blábláblá";   // Idem
a[3][1] = 20;         // Afeta b1, pois o sub-array modificado é o mesmo
a[4].um = a[4].outro; // Idem, para o objeto referenciado
delete a[4].outro;

// Visualização
document.body.innerHTML += "<pre>a = " + JSON.stringify(a) + "</pre>";
document.body.innerHTML += "<pre>b1 = a.slice() = " + JSON.stringify(b1) + "</pre>";
document.body.innerHTML += "<pre>b2 = angular.copy(a) = " + JSON.stringify(b2) + "</pre>";
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

12

If the array does not have objects that also require references, or DOM elements, ie consists of primitive* or objects/arrays of primitive* you can make a deep copy like this:

var b = JSON.parse(JSON.stringify(a));

In your example it would work properly:

var a = [1,2,3,4];
var b = JSON.parse(JSON.stringify(a));

a[0] = 3;
b[0] = "nao me copie!"
console.log(a[0]) // 3
console.log(b[0]) // nao me copie!

Note: * - about typing in Javascript read here

1

There are several ways to copy without reference, and . Slice() is one of them. However, I was having the problem that the . Slice() for arrays within arrays will take only the reference instead of actually copying, as shown in the accepted answer to this link’s question:

https://stackoverflow.com/questions/3978492/fastest-way-to-duplicate-an-array-in-javascript-slice-vs-for-loop

"Please note that These methods will clone the Array Object itself, array Contents However are copied by Reference and are not deep cloned."

array1 = [ [ [1], [2], [3] ], [ [4], [5], [6] ] ];
// array "pai", com 2 "filhos", e 6 "netos"

array2 = array1.slice();
// Copia os filhos, mas com os "netos" faz referência

So to solve this, I did the following:

for (var x = 0; x < array1.length; x++) {
    array2.push ( [ array1[0][0].slice(), array1[0][1].slice(), array1[0][2].slice() ] )
}

That at the end of the day

array1 === array2

without having any reference.

1

Using ES6:

var a = ["teste", "teste1"];
var b =[... a];

a[0] = "teste3";
b[0] = "teste4";
console.log(a) //mostrar teste3
console.log(b) //mostrar teste4

Browser other questions tagged

You are not signed in. Login or sign up in order to post.