JavaScript Clonage d'objets


Exemple

Lorsque vous voulez une copie complète d'un objet (à savoir les propriétés de l'objet et les valeurs à l'intérieur de ces propriétés, etc.), cela s'appelle le clonage profond .

5.1

Si un objet peut être sérialisé en JSON, vous pouvez en créer un clone avec une combinaison de JSON.parse et JSON.stringify :

var existing = { a: 1, b: { c: 2 } };
var copy = JSON.parse(JSON.stringify(existing));
existing.b.c = 3; // copy.b.c will not change

Notez que JSON.stringify convertira les objets Date en représentations de chaîne au format ISO, mais JSON.parse ne convertira pas la chaîne en Date .

Il n'y a pas de fonction intégrée dans JavaScript pour créer des clones profonds, et il n'est généralement pas possible de créer des clones profonds pour chaque objet pour de nombreuses raisons. Par exemple,

  • les objets peuvent avoir des propriétés non énumérables et masquées qui ne peuvent pas être détectées.
  • les getters et les setters d'objet ne peuvent pas être copiés.
  • les objets peuvent avoir une structure cyclique.
  • Les propriétés de la fonction peuvent dépendre de l'état dans une étendue cachée.

En supposant que vous ayez un objet "sympa" dont les propriétés ne contiennent que des valeurs primitives, des dates, des tableaux ou d'autres objets "sympas", la fonction suivante peut être utilisée pour créer des clones profonds. C'est une fonction récursive qui peut détecter des objets avec une structure cyclique et qui jettera une erreur dans de tels cas.

function deepClone(obj) {
    function clone(obj, traversedObjects) {
        var copy;
        // primitive types
        if(obj === null || typeof obj !== "object") {
            return obj;
        }

        // detect cycles
        for(var i = 0; i < traversedObjects.length; i++) {
            if(traversedObjects[i] === obj) {
                throw new Error("Cannot clone circular object.");
            }
        }

        // dates
        if(obj instanceof Date) {
            copy = new Date();
            copy.setTime(obj.getTime());
            return copy;
        }
        // arrays
        if(obj instanceof Array) {
            copy = [];
            for(var i = 0; i < obj.length; i++) {
                copy.push(clone(obj[i], traversedObjects.concat(obj)));
            }
            return copy;
        }
        // simple objects
        if(obj instanceof Object) {
            copy = {};
            for(var key in obj) {
                if(obj.hasOwnProperty(key)) {
                    copy[key] = clone(obj[key], traversedObjects.concat(obj));
                }
            }
            return copy;
        }
        throw new Error("Not a cloneable object.");
    }

    return clone(obj, []);
}