Skip to content
Skip to content
Menu
Info Cafe
Info Cafe

Copie d’objets en JavaScript

By admin on janvier 10, 2021

Les objets sont les blocs fondamentaux de JavaScript. Un objet est une collection de propriétés, et une propriété est une association entre une clé (ou un nom) et une valeur. Presque tous les objets en JavaScript sont des instances de Object qui se trouve au sommet de la chaîne des prototypes.

Introduction

Comme vous le savez, l’opérateur d’assignation ne crée pas une copie d’un objet, il lui attribue seulement une référence, regardons le code suivant :

let obj = { a: 1, b: 2,};let copy = obj;obj.a = 5;console.log(copy.a);// Result // a = 5;

La variable obj est un conteneur pour le nouvel objet initialisé. La variable copy pointe vers le même objet et est une référence à cet objet. Donc, en gros, cet objet { a: 1, b: 2, } dit : Il y a maintenant deux façons d’avoir accès à moi. Vous devez passer par la variable obj ou la variable copy de l’une ou l’autre façon vous arrivez quand même à moi et tout ce que vous me faites par ces moyens (passerelles) m’affectera.

L’immuabilité est largement évoquée de nos jours et vous devez écouter cet appel ! Cette méthode supprime toute forme d’immutabilité et pourrait conduire à des bugs si l’objet original est utilisé par une autre partie de votre code.

La façon naïve de copier des objets

La façon naïve de copier des objets consiste à boucler l’objet original et à copier chaque propriété l’une après l’autre. Jetons un coup d’œil à ce code :

function copy(mainObj) { let objCopy = {}; // objCopy will store a copy of the mainObj let key; for (key in mainObj) { objCopy = mainObj; // copies each property to the objCopy object } return objCopy;}const mainObj = { a: 2, b: 5, c: { x: 7, y: 4, },}console.log(copy(mainObj));

Problèmes inhérents

  1. objCopy objet a une nouvelle méthode Object.prototype différente de la méthode mainObj prototype d’objet, ce qui n’est pas ce que nous voulons. Nous voulons une copie exacte de l’objet original.
  2. Les descripteurs de propriétés ne sont pas copiés. Un descripteur « writable » dont la valeur est fixée à false sera true dans l’objet objCopy.
  3. Le code ci-dessus ne copie que les propriétés énumérables de mainObj.
  4. Si l’une des propriétés de l’objet original est un objet lui-même, alors elle sera partagée entre la copie et l’original en faisant pointer leurs propriétés respectives vers le même objet.

Copie superficielle d’objets

On dit d’un objet qu’il est copié superficiellement lorsque les propriétés sources de haut niveau sont copiées sans aucune référence et qu’il existe une propriété source dont la valeur est un objet et qui est copiée comme référence. Si la valeur source est une référence à un objet, elle ne copie que cette valeur de référence dans l’objet cible.

Une copie peu profonde dupliquera les propriétés de niveau supérieur, mais l’objet imbriqué est partagé entre l’original(source) et la copie(cible).

Utilisation de la méthode Object.assign()

La méthode Object.assign() est utilisée pour copier les valeurs de toutes les propriétés propres énumérables d’un ou plusieurs objets sources vers un objet cible.

let obj = { a: 1, b: 2,};let objCopy = Object.assign({}, obj);console.log(objCopy);// Result - { a: 1, b: 2 }

Bien, cela fait le travail jusqu’à présent. Nous avons fait une copie de obj. Voyons si l’immuabilité existe :

let obj = { a: 1, b: 2,};let objCopy = Object.assign({}, obj);console.log(objCopy); // result - { a: 1, b: 2 }objCopy.b = 89;console.log(objCopy); // result - { a: 1, b: 89 }console.log(obj); // result - { a: 1, b: 2 }

Dans le code ci-dessus, nous avons changé la valeur de la propriété 'b' dans l’objet objCopy en 89 et lorsque nous enregistrons l’objet objCopy modifié dans la console, les changements ne s’appliquent qu’à objCopy. La dernière ligne de code vérifie que l’objet obj est toujours intact et n’a pas changé. Cela implique que nous avons créé avec succès une copie de l’objet source sans aucune référence à celui-ci.

Pitfall of Object.assign()

Pas si vite ! Alors que nous avons créé avec succès une copie et que tout semble fonctionner correctement, rappelez-vous que nous avons discuté de la copie superficielle ? Jetons un coup d’œil à cet exemple:

let obj = { a: 1, b: { c: 2, },}let newObj = Object.assign({}, obj);console.log(newObj); // { a: 1, b: { c: 2} }obj.a = 10;console.log(obj); // { a: 10, b: { c: 2} }console.log(newObj); // { a: 1, b: { c: 2} }newObj.a = 20;console.log(obj); // { a: 10, b: { c: 2} }console.log(newObj); // { a: 20, b: { c: 2} }newObj.b.c = 30;console.log(obj); // { a: 10, b: { c: 30} }console.log(newObj); // { a: 20, b: { c: 30} }// Note: newObj.b.c = 30; Read why..

Pourquoi obj.b.c = 30?

Eh bien, c’est un piège de Object.assign()Object.assign ne fait que des copies superficielles. Les deux newObj.b et obj.b partagent la même référence à l’objet car des copies individuelles n’ont pas été faites, au lieu de cela une référence à l’objet a été copiée. Toute modification apportée à l’une des propriétés de l’objet s’applique à toutes les références utilisant l’objet. Comment résoudre ce problème ? Continuez à lire… nous avons un correctif dans la section suivante.

Note : les propriétés sur la chaîne de prototypes et les propriétés non énumérables ne peuvent pas être copiées. Voir ici:

let someObj = { a: 2,}let obj = Object.create(someObj, { b: { value: 2, }, c: { value: 3, enumerable: true, },});let objCopy = Object.assign({}, obj);console.log(objCopy); // { c: 3 }
  • someObj est sur la chaîne de prototype d’obj, donc il ne serait pas copié.
  • property b est une propriété non énumérable.
  • property c a un descripteur de propriété énumérable lui permettant d’être énumérable. C’est pourquoi il a été copié.

Copie profonde d’objets

Une copie profonde dupliquera chaque objet qu’elle rencontre. La copie et l’objet original ne partageront rien, il s’agira donc d’une copie de l’original. Voici la solution au problème que nous avons rencontré en utilisant Object.assign(). Explorons.

Utilisation de JSON.parse(JSON.stringify(object));

Ceci corrige le problème que nous avions précédemment. Maintenant newObj.b a une copie et non une référence ! C’est une façon de copier profondément des objets. Voici un exemple:

let obj = { a: 1, b: { c: 2, },}let newObj = JSON.parse(JSON.stringify(obj));obj.b.c = 20;console.log(obj); // { a: 1, b: { c: 20 } }console.log(newObj); // { a: 1, b: { c: 2 } } (New Object Intact!)

Immutable : ✓

Pitfall

Malheureusement, cette méthode ne peut pas être utilisée pour copier des méthodes d’objets définis par l’utilisateur. Voir ci-dessous.

Copier des méthodes d’objets

Une méthode est une propriété d’un objet qui est une fonction. Dans les exemples jusqu’à présent, nous n’avons pas copié un objet avec une méthode. Essayons-le maintenant et utilisons les méthodes que nous avons apprises pour faire des copies.

let obj = { name: 'scotch.io', exec: function exec() { return true; },}let method1 = Object.assign({}, obj);let method2 = JSON.parse(JSON.stringify(obj));console.log(method1); //Object.assign({}, obj)/* result{ exec: function exec() { return true; }, name: "scotch.io"}*/console.log(method2); // JSON.parse(JSON.stringify(obj))/* result{ name: "scotch.io"}*/

Le résultat montre que Object.assign() peut être utilisé pour copier des méthodes alors que JSON.parse(JSON.stringify(obj)) ne peut pas être utilisé.

Copier des objets circulaires

Les objets circulaires sont des objets qui ont des propriétés qui se référencent elles-mêmes. Utilisons les méthodes de copie d’objets que nous avons apprises jusqu’à présent pour faire des copies d’un objet circulaire et voir si cela fonctionne.

Utilisation de JSON.parse(JSON.stringify(object))

Essayons JSON.parse(JSON.stringify(object)):

// circular objectlet obj = { a: 'a', b: { c: 'c', d: 'd', },}obj.c = obj.b;obj.e = obj.a;obj.b.c = obj.c;obj.b.d = obj.b;obj.b.e = obj.b.c;let newObj = JSON.parse(JSON.stringify(obj));console.log(newObj); 

Voici le résultat :

JSON.parse(JSON.stringify(obj)) ne fonctionne clairement pas pour les objets circulaires.

Utilisation de Object.assign()

Essayons Object.assign():

// circular objectlet obj = { a: 'a', b: { c: 'c', d: 'd', },}obj.c = obj.b;obj.e = obj.a;obj.b.c = obj.c;obj.b.d = obj.b;obj.b.e = obj.b.c;let newObj2 = Object.assign({}, obj);console.log(newObj2); 

Voici le résultat :

Object.assign() fonctionne bien pour la copie superficielle d’objets circulaires mais ne fonctionnerait pas pour la copie profonde. N’hésitez pas à explorer la circular object tree sur la console de votre navigateur. Je suis sûr que vous y trouverez beaucoup de travail intéressant.

Utilisation des éléments d’étalement (… )

ES6 a déjà des éléments de repos pour l’affectation de déstructuration de tableau et des éléments d’étalement pour les littéraux de tableau implémentés. Jetez un coup d’œil à la mise en œuvre de l’élément spread sur un tableau ici:

const array = ;const newArray = ;console.log(newArray);// Result // 

La propriété spread pour les littéraux d’objet est actuellement une proposition de phase 3 pour ECMAScript. Les propriétés de propagation dans les initialisateurs d’objets copient les propriétés énumérables propres d’un objet source sur l’objet cible. L’exemple ci-dessous montre comment il serait facile de copier un objet une fois que la proposition a été acceptée.

let obj = { one: 1, two: 2,}let newObj = { ...z };// { one: 1, two: 2 }

Note : Cela sera juste efficace pour la copie superficielle

Conclusion

Copier des objets en JavaScript peut être assez intimidant, surtout si vous êtes nouveau en JavaScript et ne connaissez pas votre chemin dans le langage. Espérons que cet article vous a aidé à comprendre et à éviter les futurs pièges que vous pourriez rencontrer en copiant des objets. Si vous avez une bibliothèque ou un morceau de code qui permet d’obtenir un meilleur résultat, n’hésitez pas à partager avec la communauté. Bon codage!

Navigation de l’article

Kroger Weekly Ad (2/24/21 – 3/2/21) & Kroger Ad Preview Sneak Peek
Comment faire un CD/DVD/USB amorçable pour installer Windows

Laisser un commentaire Annuler la réponse

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Articles récents

  • Firebush (Français)
  • 9 Meilleures vitamines et suppléments pour chiens pour une santé améliorée
  • Prévision des taux des CD pour 2021 : Les taux resteront probablement bas, mais ils pourraient augmenter plus tard dans l’année
  • Comment structurer la documentation du système de management de la qualité
  • Douleur pelvienne chronique et prostatite : symptômes, diagnostic et traitement
  • Croustillant aux baies mélangées
  • Recette de pudding au chocolat à faible teneur en glucides
  • Jeux et activités sains pour les enfants | Informatique en ligne de l’UIC
  • Wheat Ales (American)
  • Les bienfaits de l’allaitement maternel au-delà d’un an

Méta

  • Connexion
  • Flux des publications
  • Flux des commentaires
  • Site de WordPress-FR

Archives

  • mars 2021
  • février 2021
  • janvier 2021
  • décembre 2020
  • DeutschDeutsch
  • NederlandsNederlands
  • EspañolEspañol
  • FrançaisFrançais
  • PortuguêsPortuguês
  • ItalianoItaliano
  • PolskiPolski
  • 日本語日本語
©2021 Info Cafe | WordPress Theme by SuperbThemes.com