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, de sorte qu'ils sont totalement indépendants? Je ne veux pas changer un élément dans un tableau pour affecter l'autre.

37
demandé sur Eric Smekens 2013-04-26 13:20:27

7 réponses

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

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

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

À partir de ES2015 (aka ES6), il y a aussi Array.from, qui crée un nouveau tableau à partir de n'importe quelle chose de type tableau (y compris un tableau réel):

var destinationArray = Array.from(sourceArray);

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

Aussi à partir D'ES2015, vous pouvez utiliser la notation de propagation de tableau et un tableau littéral avec tout itérable (y compris un tableau réel):

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 pointera vers le même objet; ce n'est pas une copie "profonde".

Si le tableau de destination existe...

...et vous voulez y ajouter le contenu du tableau source, vous pouvez utiliser push:

destinationArray.push.apply(destinationArray, sourceArray);

Qui fonctionne par appeler push sur le tableau de destination en utilisant la fonctionnalité apply des fonctions JavaScript, qui vous permet de spécifier les arguments de l'appel de fonction en tant que tableau. {[13] } va pousser autant d'éléments qu'il a d'arguments, donc il finit par copier les éléments du tableau source vers le tableau de destination.

Dans ES2015 et versions ultérieures, vous pouvez rendre ce nettoyant avec la notation spread(...):

destinationArray.push(...sourceArray);

Notez que dans les deux cas, l'appel est limité par le nombre maximum du moteur JavaScript des arguments de fonction (à ce jour, c'est au moins dans les milliers pour tous les principaux moteurs [et pas dans les 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>
72
répondu T.J. Crowder 2018-09-03 10:34:35

Moyen Facile d'obtenir ce travail est d'utiliser:

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

J'ai des problèmes avec arr.concat() ou arr.splice(0) pour donner une copie profonde. Ci-dessus extrait fonctionne parfaitement.

18
répondu jsbisht 2015-02-12 16:40:08
var clonedArray = array.concat();
3
répondu Ilya 2013-04-26 09:27:29

Un excellent moyen de cloner un tableau est avec 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 les opérateurs de propagation https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator#Copy_an_array

C'est aussi une bonne pratique Airbnb. https://github.com/airbnb/javascript#es6-array-spreads

Note : Généralement, les opérateurs de propagation dans ES2015 vont d'un niveau en profondeur lors de la copie d'un tableau. Par conséquent, ils ne conviennent pas à la copie de tableaux multidimensionnels.

2
répondu MauricioLeal 2017-03-27 21:20:34

Si vous voulez garder la référence:

Array.prototype.push.apply(destinationArray, sourceArray);

1
répondu Veikko Karsikko 2016-04-20 18:02:24

Il y a deux notes importantes.

  1. L'utilisation de array.concat() ne fonctionne pas en utilisant Angular 1.4.4 et jQuery 3.2.1 (c'est mon environnement).
  2. Le 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 feront référence à seulement 1 Tableau et changer l'un affectera l'autre.

Alternativement, l'utilisation de newArray1 = JSON.parse(JSON.stringify(old array)) ne copiera que la valeur, créant ainsi un nouveau tableau à chaque fois.

1
répondu Tran Vu Dang Khoa 2017-08-22 10:21:26

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

0
répondu bean5 2014-12-11 07:34:02