Si je clone un tableau, j'utilise cloneArr = arr.slice()
Je veux savoir comment cloner un objet dans nodejs.
Réponses:
Pour les utilitaires et les classes où il n'est pas nécessaire de réduire chaque goutte de performance, je triche souvent et j'utilise simplement JSON pour effectuer une copie complète:
function clone(a) {
return JSON.parse(JSON.stringify(a));
}
Ce n'est pas la seule réponse ou la réponse la plus élégante; toutes les autres réponses doivent être prises en compte pour les goulots d'étranglement de la production. Cependant, c'est une solution rapide et sale, assez efficace et utile dans la plupart des situations où je clonerais un simple hachage de propriétés.
newObj = obj.clone(args...);
Object.assign n'a été mentionné dans aucune des réponses ci-dessus.
let cloned = Object.assign({}, source);
Si vous êtes sur ES6, vous pouvez utiliser l'opérateur de diffusion:
let cloned = { ... source };
Référence: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
let a = {x:1}; let b = Object.assign({}, a); a.x = 2; a.y = 1; console.log(a, b);
Il y a quelques modules Node là-bas si vous ne voulez pas "rouler vous-même". Celui-ci a l'air bien: https://www.npmjs.com/package/clone
On dirait qu'il gère toutes sortes de choses, y compris les références circulaires. Depuis la page github :
clone maîtrise les objets de clonage, les tableaux, les objets Date et les objets RegEx. Tout est cloné de manière récursive, de sorte que vous pouvez cloner des dates dans des tableaux dans des objets, par exemple. [...] Références circulaires? Oui!
Il est difficile de faire une opération de clonage générique mais utile car ce qui doit être cloné récursivement et ce qui doit être simplement copié dépend de la façon dont l'objet spécifique est censé fonctionner.
Quelque chose qui peut être utile est
function clone(x)
{
if (x === null || x === undefined)
return x;
if (typeof x.clone === "function")
return x.clone();
if (x.constructor == Array)
{
var r = [];
for (var i=0,n=x.length; i<n; i++)
r.push(clone(x[i]));
return r;
}
return x;
}
Dans ce code, la logique est
nullou undefinedretournez simplement le même (le cas particulier est nécessaire car c'est une erreur d'essayer de voir si unclone méthode est présente)clone méthode? alors utilise çaCette fonction de clonage devrait permettre d'implémenter facilement des méthodes de clonage personnalisées ... par exemple
function Point(x, y)
{
this.x = x;
this.y = y;
...
}
Point.prototype.clone = function()
{
return new Point(this.x, this.y);
};
function Polygon(points, style)
{
this.points = points;
this.style = style;
...
}
Polygon.prototype.clone = function()
{
return new Polygon(clone(this.points),
this.style);
};
Lorsque dans l'objet vous savez qu'une opération de clonage correcte pour un tableau spécifique n'est qu'une copie superficielle, vous pouvez appeler values.slice()au lieu declone(values) .
Par exemple, dans le code ci-dessus, je demande explicitement qu'un clonage d'un objet polygonal clonera les points, mais partagera le même objet de style. Si je veux aussi cloner l'objet de style à la place, je peux simplement passer clone(this.style).
.cloneméthode eux-mêmes. C'est la meilleure façon de gérer le clonage d'objets.
if (x.clone)devrait êtreif (typeof x.clone === 'function')
Il n'existe pas de méthode native pour cloner des objets. Underscore implements _.clonequi est un clone superficiel.
_.clone = function(obj) {
return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
};
Il le tranche ou le prolonge.
Voici _.extend
// extend the obj (first parameter)
_.extend = function(obj) {
// for each other parameter
each(slice.call(arguments, 1), function(source) {
// loop through all properties of the other objects
for (var prop in source) {
// if the property is not undefined then add it to the object.
if (source[prop] !== void 0) obj[prop] = source[prop];
}
});
// return the object (first parameter)
return obj;
};
Extend itère simplement à travers tous les éléments et crée un nouvel objet avec les éléments qu'il contient.
Vous pouvez déployer votre propre implémentation naïve si vous le souhaitez
function clone(o) {
var ret = {};
Object.keys(o).forEach(function (val) {
ret[val] = o[val];
});
return ret;
}
Il y a de bonnes raisons d'éviter le clonage profond car les fermetures ne peuvent pas être clonées.
J'ai personnellement posé une question deep cloning objects beforeet la conclusion à laquelle je suis arrivé est que vous ne le faites tout simplement pas.
Ma recommandation est l'utilisation underscoreet sa _.cloneméthode pour les clones peu profonds
Pour une copie superficielle, j'aime utiliser le modèle de réduction (généralement dans un module ou autre), comme ceci:
var newObject = Object.keys(original).reduce(function (obj, item) {
obj[item] = original[item];
return obj;
},{});
Voici un jsperf pour quelques options: http://jsperf.com/shallow-copying
Ancienne question, mais il y a une réponse plus élégante que ce qui a été suggéré jusqu'à présent; utilisez les utils._extend intégrés:
var extend = require("util")._extend;
var varToCopy = { test: 12345, nested: { val: 6789 } };
var copiedObject = extend({}, varToCopy);
console.log(copiedObject);
// outputs:
// { test: 12345, nested: { val: 6789 } }
Notez l'utilisation du premier paramètre avec un objet vide {} - cela indique à extend que le ou les objets copiés doivent être copiés dans un nouvel objet. Si vous utilisez un objet existant comme premier paramètre, le second (et tous les suivants) paramètres seront copiés en profondeur sur la première variable de paramètre.
En utilisant les exemples de variables ci-dessus, vous pouvez également faire ceci:
var anotherMergeVar = { foo: "bar" };
extend(copiedObject, { anotherParam: 'value' }, anotherMergeVar);
console.log(copiedObject);
// outputs:
// { test: 12345, nested: { val: 6789 }, anotherParam: 'value', foo: 'bar' }
Utilitaire très pratique, en particulier là où je suis habitué à étendre AngularJS et jQuery.
J'espère que ceci aide quelqu'un d'autre; les écrasements de références d'objets sont une misère, et cela le résout à chaque fois!
En fonction de ce que vous voulez faire avec votre objet cloné, vous pouvez utiliser le mécanisme d'héritage prototypique de javascript et obtenir un objet quelque peu cloné via:
var clonedObject = Object.create(originalObject);
N'oubliez pas que ce n'est pas un clone complet - pour le meilleur ou pour le pire.
Une bonne chose à ce sujet est que vous n'avez en fait pas dupliqué l'objet, donc l'empreinte mémoire sera faible.
Certaines choses difficiles à retenir à propos de cette méthode sont que l'itération des propriétés définies dans la chaîne de prototypes fonctionne parfois un peu différemment et le fait que toute modification apportée à l'objet d'origine affectera également l'objet cloné à moins que cette propriété n'ait également été définie sur elle-même. .
var a = {foo: "bar"}, b = Object.create(a); a.foo = "broken"; console.log(b.foo); // "broken";
b.foo = "working"; console.log(a.foo); // still "broken";Il faut bien sûr être conscient que les modifications de l'objet d'origine seront reflétées dans le "clone" et que les modifications du "clone" ne seront pas reflétées dans l'objet d'origine - mais je n'appellerais pas cela dangereux - tout dépend de ce que vous voulez faire avec votre clone
J'ai implémenté une copie complète complète. Je pense que c'est le meilleur choix pour une méthode de clonage générique, mais elle ne gère pas les références cycliques.
parent = {'prop_chain':3}
obj = Object.create(parent)
obj.a=0; obj.b=1; obj.c=2;
obj2 = copy(obj)
console.log(obj, obj.prop_chain)
// '{'a':0, 'b':1, 'c':2} 3
console.log(obj2, obj2.prop_chain)
// '{'a':0, 'b':1, 'c':2} 3
parent.prop_chain=4
obj2.a = 15
console.log(obj, obj.prop_chain)
// '{'a':0, 'b':1, 'c':2} 4
console.log(obj2, obj2.prop_chain)
// '{'a':15, 'b':1, 'c':2} 4
Ce code copie les objets avec leurs prototypes, il copie également des fonctions (peut être utile pour quelqu'un).
function copy(obj) {
// (F.prototype will hold the object prototype chain)
function F() {}
var newObj;
if(typeof obj.clone === 'function')
return obj.clone()
// To copy something that is not an object, just return it:
if(typeof obj !== 'object' && typeof obj !== 'function' || obj == null)
return obj;
if(typeof obj === 'object') {
// Copy the prototype:
newObj = {}
var proto = Object.getPrototypeOf(obj)
Object.setPrototypeOf(newObj, proto)
} else {
// If the object is a function the function evaluate it:
var aux
newObj = eval('aux='+obj.toString())
// And copy the prototype:
newObj.prototype = obj.prototype
}
// Copy the object normal properties with a deep copy:
for(var i in obj) {
if(obj.hasOwnProperty(i)) {
if(typeof obj[i] !== 'object')
newObj[i] = obj[i]
else
newObj[i] = copy(obj[i])
}
}
return newObj;
}
Avec cette copie, je ne trouve aucune différence entre l'original et le copié, sauf si l'original a utilisé des fermetures sur sa construction, donc je pense que c'est une bonne mise en œuvre.
J'espère que ça aide
Les objets et les tableaux en JavaScript utilisent l'appel par référence, si vous mettez à jour la valeur copiée, cela peut se refléter sur l'objet d'origine. Pour éviter cela, vous pouvez cloner l'objet en profondeur, pour empêcher la transmission de la référence, à l'aide de la commande d' exécution de la méthode cloneDeep de la bibliothèque lodash
npm installer lodash
const ld = require('lodash')
const objectToCopy = {name: "john", age: 24}
const clonedObject = ld.cloneDeep(objectToCopy)