180 votes

Est-ce une bonne façon de cloner un objet en ES6 ?

En cherchant sur Google "javascript clone object", on obtient des résultats vraiment étranges, certains sont désespérément dépassés et d'autres sont tout simplement trop complexes, n'est-ce pas aussi simple que ça ?

let clone = {...original};

Y a-t-il quelque chose de mal à cela ?

2 votes

Ce n'est pas une ES6 légale. Mais si c'était le cas, ce n'est pas un clone : les propriétés du clone et de l'original pointent toutes deux vers les mêmes choses maintenant. Par exemple, original = { a: [1,2,3] } vous donne un clone avec clone.a étant littéralement original.a . Modification par soit clone o original modifie la même chose donc non, c'est mauvais =)

2 votes

@AlbertoRivera C'est un peu comme JavaScript valide, dans la mesure où il s'agit d'un étape 2 qui sera probablement un ajout futur à la norme JavaScript.

0 votes

@Frxstrem la question portant sur ES6, ce n'est pas du JavaScript valide =)

274voto

Mark Shust Points 639

C'est bien. pour un clonage peu profond . Le site La propagation d'objets est un élément standard de l'ECMAScript 2018. .

Pour le clonage profond, vous aurez besoin d'un solution différente .

const clone = {...original} à un clone peu profond

const newobj = {...original, prop: newOne} pour ajouter de façon immuable un autre accessoire à l'original et le stocker comme un nouvel objet.

19 votes

Cependant, ne s'agit-il pas simplement d'un clone superficiel ? En effet, les propriétés ne sont pas clonées de manière récursive, n'est-ce pas ? Par conséquent, original.innerObject === clone.innerObject et la modification de original.innerObject.property modifiera clone.innerObject.property.

23 votes

Oui, c'est un clone peu profond. si vous voulez un clone profond, vous devez utiliser JSON.parse(JSON.stringify(input))

9 votes

/!\ JSON.parse(JSON.stringify(input)) gâche les dates, les indéfinis, ... Ce n'est pas la solution miracle pour le clonage ! Voir : maxpou.fr/immutabilité-js-sans-librairie

69voto

Alberto Rivera Points 1446

EDIT : Quand cette réponse a été postée, {...obj} n'était pas disponible dans la plupart des navigateurs. Aujourd'hui, vous devriez pouvoir l'utiliser sans problème (sauf si vous devez prendre en charge IE 11).

Utilisez Object.assign.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

var obj = { a: 1 };
var copy = Object.assign({}, obj);
console.log(copy); // { a: 1 }

Cependant, cela ne fera pas un clone profond. Il n'existe pas encore de méthode native de clonage profond.

EDIT : Comme @Mike 'Pomax' Kamermans l'a mentionné dans les commentaires, vous pouvez cloner profondément des objets simples (c'est-à-dire sans prototypes, fonctions ou références circulaires) en utilisant JSON.parse(JSON.stringify(input))

20 votes

Il y en a un, à condition que votre objet soit un véritable objet littéral, et purement des données, auquel cas JSON.parse(JSON.stringify(input)) est un clone profond approprié. Cependant, dès que des prototypes, des fonctions ou des références circulaires sont en jeu, cette solution ne fonctionne plus.

0 votes

@Mike'Pomax'Kamermans C'est vrai. La perte de fonctionnalité pour les getters et setters est terrible, cependant...

0 votes

Si vous avez besoin d'une fonction générique pour cloner en profondeur n'importe quel objet, jetez un coup d'œil à stackoverflow.com/a/13333781/560114 .

6voto

shaheer shukur Points 117

Si les méthodes que vous avez utilisées ne fonctionnent pas bien avec des objets impliquant des types de données tels que Date Essayez ceci

Importation _

import * as _ from 'lodash';

Objet de clonage profond

myObjCopy = _.cloneDeep(myObj);

3voto

rafee_que_ Points 423

Vous pouvez aussi le faire comme ça,

let copiedData = JSON.parse(JSON.stringify(data));

3voto

marcel Points 1450

Si vous ne voulez pas utiliser json.parse(json.stringify(object)), vous pouvez créer récursivement des copies clé-valeur :

function copy(item){
  let result = null;
  if(!item) return result;
  if(Array.isArray(item)){
    result = [];
    item.forEach(element=>{
      result.push(copy(element));
    });
  }
  else if(item instanceof Object && !(item instanceof Function)){ 
    result = {};
    for(let key in item){
      if(key){
        result[key] = copy(item[key]);
      }
    }
  }
  return result || item;
}

Mais le meilleur moyen est de créer une classe qui peut renvoyer un clone de son propre corps.

class MyClass{
    data = null;
    constructor(values){ this.data = values }
    toString(){ console.log("MyClass: "+this.data.toString(;) }
    remove(id){ this.data = data.filter(d=>d.id!==id) }
    clone(){ return new MyClass(this.data) }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X