web-dev-qa-db-fra.com

Copier un tableau d'objets dans un autre tableau en javascript

Comment puis-je copier chaque élément d'un tableau (où les éléments sont des objets), dans un autre tableau, afin qu'ils soient totalement indépendants Je ne veux pas que la modification d'un élément d'un tableau affecte l'autre.

41
hAlE

Si le tableau de destination n'existe pas encore ...

... vous pouvez utiliser slice() ou concat(). slice() est probablement plus idiomatique (vous verrez également slice(0), mais la valeur par défaut est 0, donc ...):

var destinationArray = sourceArray.slice(); // Probably more idiomatic
// or
var destinationArray = sourceArray.concat();

Depuis ES2015 (alias ES6), il existe également Array.from, qui crée un nouveau tableau à partir de n’importe quel élément semblable à un tableau (y compris un tableau réel):

var destinationArray = Array.from(sourceArray);

(Array.from peut être calé/rempli pour les moteurs JavaScript plus anciens.)

De plus, à partir de ES2015, vous pouvez utiliser la notation étalée itérable et un littéral de tableau avec n'importe quel caractère itérable (y compris un tableau):

var destinationArray = [...sourceArray];

Après cela, les deux tableaux auront le même contenu. Changer un tableau ne changera pas l'autre. Naturellement, si une entrée de tableau est un objet, l'entrée de cet objet dans les deux tableaux pointe vers le même objet; ce n'est pas une copie "profonde".

Si le tableau de destination existe ...

... et que vous souhaitez y ajouter le contenu du tableau source, vous pouvez utiliser Push:

destinationArray.Push.apply(destinationArray, sourceArray);

Cela fonctionne en appelant Push sur le tableau de destination à l'aide de la fonction apply des fonctions JavaScript, qui vous permet de spécifier les arguments de l'appel de fonction sous forme de tableau. Push va pousser autant d’éléments qu’il a de paramètres, de sorte qu’il finit par copier les éléments du tableau source dans le tableau de destination.

Dans ES2015 et les versions ultérieures, vous pouvez rendre ce nettoyeur plus clair avec la notation étalable et répétable (...):

destinationArray.Push(...sourceArray);

Notez que dans les deux cas, l'appel est limité par le nombre maximal d'arguments de fonction du moteur JavaScript (au moment d'écrire ces lignes, il en existe au moins des milliers pour tous les moteurs principaux [et non des centaines de milliers, du moins pas pour le V8 de Chrome. ]).

Voici une version ES5:

var source1, dest1, source2, dest2;

snippet.log("If dest doesn't exist yet:");
source1 = [1, 2, 3, 4];
dest1 = source1.slice(0);
snippet.log("[before change] source1 = " + source1.join(", "));
snippet.log("[before change] dest1 = " + dest1.join(", "));
source1[2] = "three";
dest1[3] = "four";
snippet.log("[after change] source1 = " + source1.join(", "));
snippet.log("[after change] dest1 = " + dest1.join(", "));

snippet.log("If dest already exists and we're just appending:");
source2 = [1, 2, 3, 4];
dest2 = ['a', 'b', 'c', 'd'];
snippet.log("[before append] source2 = " + source2.join(", "));
snippet.log("[before append] dest2 = " + dest2.join(", "));
dest2.Push.apply(dest2, source2);
snippet.log("[before change] source2 = " + source2.join(", "));
snippet.log("[before change] dest2 = " + dest2.join(", "));
source2[2] = "three";
dest2[7] = "four";
snippet.log("[after change] source2 = " + source2.join(", "));
snippet.log("[after change] dest2 = " + dest2.join(", "));
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="//tjcrowder.github.io/simple-snippets-console/snippet.js"></script>

84
T.J. Crowder

Un moyen facile d'obtenir ce travail fonctionne en utilisant:

var cloneArray = JSON.parse(JSON.stringify(originalArray));

Je ne parviens pas à obtenir arr.concat() ou arr.splice(0) pour en obtenir une copie conforme. L'extrait ci-dessus fonctionne parfaitement.

20
jsbisht
var clonedArray = array.concat();
3
Ilya

Un excellent moyen de cloner un tableau consiste à utiliser un littéral array et l'opérateur spread. Ceci est rendu possible par ES2015

let objArray = [{name:'first'}, {name:'second'}, {name:'third'}, {name:'fourth'}];

let clonedArr = [...objArray];

console.log(clonedArr) // [Object, Object, Object, Object]

Vous pouvez trouver cette option de copie dans la documentation de MDN pour opérateurs de diffusion} _ https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator#Copy_an_array

C’est également la meilleure pratique de Airbnb. https://github.com/airbnb/javascript#es6-array-spreads

Note: généralement, les opérateurs de propagation dans ES2015 approfondissent un niveau lors de la copie d'un tableau. Par conséquent, ils ne conviennent pas pour la copie de tableaux multidimensionnels. 

2
MauricioLeal

Il y a deux notes importantes.

  1. L'utilisation de array.concat() ne fonctionne pas avec Angular 1.4.4 et jQuery 3.2.1 (il s'agit de mon environnement).
  2. array.slice(0) est un objet. Donc, si vous faites quelque chose comme newArray1 = oldArray.slice(0); newArray2 = oldArray.slice(0), les deux nouveaux tableaux ne feront référence qu’à un tableau et la modification d’un tableau affectera l’autre.

Sinon, l'utilisation de newArray1 = JSON.parse(JSON.stringify(old array)) ne copie que la valeur, ce qui crée un nouveau tableau à chaque fois.

1
Tran Vu Dang Khoa

Je suggère d'utiliser concat() si vous utilisez nodeJS. Dans tous les autres cas, j'ai trouvé que slice(0) fonctionnait bien.

0
bean5