Quel est le moyen le plus efficace de cloner un objet JavaScript ? J'ai vu l'utilisation de obj = eval(uneval(o));
, mais [ce n'est pas standard et n'est supporté que par Firefox][1].
J'ai fait des choses comme obj = JSON.parse(JSON.stringify(o));
mais je m'interroge sur l'efficacité.
J'ai aussi vu des fonctions de copie récursive avec divers défauts.
Je suis surpris qu'il n'existe pas de solution canonique.
[1] : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/uneval
C'est ce qu'on appelle le "clonage structuré", qui fonctionne expérimentalement dans Node 11 et les versions ultérieures, et qui, espérons-le, sera disponible dans les navigateurs. Voir cette réponse pour plus de détails.
Si vous n'utilisez pas de Date
s, de fonctions, de undefined
, de Infinity
, de RegExps, de Maps, de Sets, de Blobs, de FileLists, d'ImageDatas, de sparse Arrays, de Typed Arrays ou d'autres types complexes dans votre objet, une méthode très simple pour cloner profondément un objet est :
JSON.parse(JSON.stringify(object))
.
const a = {
string: 'string',
number: 123,
bool: false,
nul: null,
date: new Date(), // stringified
undef: undefined, // lost
inf: Infinity, // forced to 'null'
re: /.*/, // lost
}
console.log(a);
console.log(typeof a.date); // Date object
const clone = JSON.parse(JSON.stringify(a));
console.log(clone);
console.log(typeof clone.date); // result of .toISOString()
Voir la réponse de Corban pour des points de repère.
Puisque le clonage d'objets n'est pas trivial (types complexes, références circulaires, fonction etc.), la plupart des bibliothèques majeures fournissent une fonction pour cloner des objets. Ne réinventez pas la roue - si vous utilisez déjà une bibliothèque, vérifiez si elle possède une fonction de clonage d'objets. Par exemple,
cloneDeep
; peut être importé séparément via le module lodash.clonedeep et est probablement votre meilleur choix si vous n'utilisez pas déjà une bibliothèque qui fournit une fonction de clonage profondangular.copy
jQuery.extend(true, { }, oldObject)
; .clone()
ne clone que les éléments du DOM.Pour être complet, notez que ES6 offre deux mécanismes de copie superficielle : Object.assign()
et l'opérateur spread.
S'il n'y en avait pas un intégré, vous pourriez essayer :
function clone(obj) {
if (obj === null || typeof (obj) !== 'object' || 'isActiveClone' in obj)
return obj;
if (obj instanceof Date)
var temp = new obj.constructor(); //or new Date(obj);
else
var temp = obj.constructor();
for (var key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
obj['isActiveClone'] = null;
temp[key] = clone(obj[key]);
delete obj['isActiveClone'];
}
}
return temp;
}