Copie profonde
==============

Une **copie profonde** d'un objet est une copie dont les propriétés ne partagent pas les mêmes références (ne pointent pas vers les mêmes valeurs sous-jacentes) que celles de l'objet source de laquelle la copie a été faite. Par conséquent, lorsque vous modifiez la source ou la copie, vous pouvez être assuré que vous ne modifiez pas également l'autre objet ; c'est-à-dire que vous ne provoquerez pas involontairement des modifications inattendues de la source ou de la copie. Ce comportement contraste avec celui d'une copie superficielle (en-US), dans lequel les modifications apportées à la source ou à la copie peuvent également entraîner la modification de l'autre objet (car les deux objets partagent les mêmes références).

En JavaScript, les opérations de copie d'objet intégrées standards (telles que la syntaxe de décomposition, `Array.prototype.concat()`, `Array.prototype.slice()`, `Array.from()`, `Object.assign()`, et `Object.create()`) ne créent pas de copies profondes. Au lieu de cela, ils créent des copies superficielles.

Une façon de faire une copie complète d'un objet JavaScript, s'il peut être sérialisé, est d'utiliser `JSON.stringify()` pour convertir l'objet en une chaîne JSON, puis de reconvertir la chaîne en un (entièrement nouvel) objet JavaScript avec `JSON.parse()` :


```js
let liste_ingredients = ["nouilles", { liste: ["œufs", "farine", "eau"] }];
let liste_ingredients_copieprofonde = JSON.parse(
  JSON.stringify(liste_ingredients),
);

// Modifier la valeur de la propriété 'liste' dans liste\_ingredients\_copieprofonde
liste_ingredients_copieprofonde[1].liste = ["farine de riz", "water"];
// La propriété 'liste' ne change pas dans liste\_ingredients
console.log(liste_ingredients[1].liste);
// Array(3) [ "œufs", "farine", "eau" ]
```


Comme le montre le code ci-dessus, étant donné qu'une copie complète ne partage aucune référence avec son objet source, toute modification apportée à la copie complète n'affecte pas l'objet source.

Cependant, alors que l'objet dans le code ci-dessus est assez simple pour être sérialisable, de nombreux objets JavaScript ne sont pas du tout sérialisables — par exemple, les fonctions (avec des fermetures), les symboles, les objets qui représentent des éléments HTML dans l'API HTML DOM (en-US), les données récursives, et bien d'autres cas. L'appel de `JSON.stringify()` pour sérialiser ces objets échouera. Il n'y a donc aucun moyen de faire des copies complètes de tels objets.

Pour les objets qui *sont* sérialisables, vous pouvez également utiliser la méthode `structuredClone()` (en-US) pour créer des copies profondes. `structuredClone()` est avantageuse car elle permet de *transférer* des objets transférables (en-US) dans la source vers la nouvelle copie, plutôt que de simplement les cloner. Mais notez que `structuredClone()` n'est pas une fonctionnalité du langage JavaScript lui-même — il s'agit plutôt d'une fonctionnalité des navigateurs et de tout autre environnement d'exécution de JavaScript qui implémente un objet global comme `window`, et appeler `structuredClone()` pour cloner un objet non sérialisable échouera de la même manière que l'appel de `JSON.stringify()` pour le sérialiser échouera.

Voir aussi
----------

* Copie superficielle (en-US)
* `window.structuredClone()` (en-US)