web-dev-qa-db-fra.com

Quelle est la différence entre Object.assign et JSON.parse (JSON.stringify (obj)) pour le clonage en profondeur d'un objet?

Je veux savoir s'il y a une différence entre

Object.assign({}, obj)

et

JSON.parse(JSON.stringify(obj))

pour le clonage en profondeur d'un objet? Quelqu'un peut-il expliquer s'il a une idée?

28
Ram

La différence est que

Object.assign({}, obj)

crée un copie superficielle , pas deep , tandis que

JSON.parse(JSON.stringify(obj))

sérialise l'objet sous forme de chaîne JSON puis le désérialise, créant efficacement une copie complète.

Une copie superficielle est très bien, si toutes vos propriétés pointent vers des valeurs primitives, ou si vous n'avez pas l'intention de muter les objets référencés par la copie. Si vous le faites, les modifications seront visibles à la fois dans l'original et dans la copie superficielle, car elles font toutes deux référence au même objet:

> let a = { k: { h: 1 } };
> let b = Object.assign({}, a);
> b.k.h = 2;
> a
{ k: { h: 2 } }
> b
{ k: { h: 2 } }

Vous pouvez bien sûr muter la copie elle-même sans que cela n'ait d'effet sur l'original:

> b.j = 4
> b.k = { new: 'object' }
> a
{ k: { h: 2 } }
> b
{ k: { new: 'object' }, j: 4 }

L'astuce serialize-deserialize, d'autre part, crée une copie complète où tout est créé à partir de zéro:

> let c = JSON.parse(JSON.stringify(b));
> c
{ k: { h: 2 } }
> c.k.h = 3
> c
{ k: { h: 3 } }
> a
{ k: { h: 2 } }
> b
{ k: { h: 2 } }

Une autre façon d'inspecter les identités consiste à utiliser une stricte égalité:

> let a = { k: { h: 1 } };
> let b = Object.assign({}, a);
> a.k === b.k  // both point to the same object
true
> let c = JSON.parse(JSON.stringify(b));
> c.k === b.k  // different objects
false
38
Ilja Everilä