« »
2/25/2009

Réaliser une copie profonde d’objet (deep copy) en Javascript

Un des problèmes récurrent avec Javascript est qu’il est difficile de savoir si une variable passée par référence ou par valeur.

En VB (VB6, VB.NET) il est possible de déclarer dans l’entête de la fonction by val ou by ref pour préciser le mode de passage mais ce n’est pas le cas en Javascript.

//Création de l'objet monObjet
var monObjet = new Object();

// monDeuxiemeObjet réfère à l'objet monObjet
var monDeuxiemeObjet = monObjet;

// On modifie une propriété du premier objet
monObjet.unePropriete = true;

// Les changements sont aussi appliqué sur le second objet
// (Le deuxième objet réfère au premier objet)
alert( monObjet.unePropriete === monDeuxiemeObjet.unePropriete );//affiche true

 

Dans cette exemple, la copie de monObjet dans monDeuxiemeObjet à été effectuée par référence, ce qui signifie que monDeuxiemeObjet pointe vers l’adresse de monObjet (même si la réalité est un peu plus complexe que cela…monDeuxiemeObjet pointe sur la référence de l’objet final monObjet mais c’est une autre histoire).

 

Seulement dans certains cas, il arrive que nous ayons besoin de réaliser une vrai copie. Par exemple sauvegarder monObjet dans une variable temporaire et effectuer des traitements uniquement sur cette variable sans que cela n’affecte monObjet. Dans certains cas là méthode que je vous propose n’est pas indispensable notamment dans le cas où l’objet à copier n’est pas complexe.

 

Heureusement jQuery intègre la méthode extend. Basiquement elle permet de gérer l’héritage d’un objet vers un à plusieurs autres objets. Mais elle permet aussi la copie profonde (deep copy) d’un objet vers un autre et donc une copie par valeur (et non plus par référence) via son paramètre optionnel “deep”.

 

jQuery.extend( [deep], target, object1, [objectN] )

 

//Création de l'objet monObjet
var monObjet = new Object();

var monDeuxiemeObjet = {};
$.extend(true,monObjet,monDeuxiemeObjet);//deep copy

// On modifie une propriété du premier objet
monObjet.unePropriete = true;

// Les changements ne sont pas appliqué sur le second objet
// monDeuxiemeObjet.unePropriete est indéfini
alert( monObjet.unePropriete === monDeuxiemeObjet.unePropriete );//affiche false

Ici, monDeuxiemeObjet ne réfère plus à monObjet. Ces deux objets possèdent chacun leurs propres adresses mémoires, il est ainsi possible de travailler sur l’un sans modifier l’autre.

« »
 
 
Made with on a hot august night.
http://bit.ly/1II1u5L