Si je clone un tableau, j'utilise cloneArr = arr.slice()
Je veux savoir comment cloner un objet dans nodejs.
Si je clone un tableau, j'utilise cloneArr = arr.slice()
Je veux savoir comment cloner un objet dans nodejs.
Pour les utilitaires et les classes où il n'est pas nécessaire d'exploiter chaque goutte de performance, je triche souvent et j'utilise simplement JSON pour effectuer une copie profonde :
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 goulets d'étranglement de la production. Cependant, il s'agit d'une solution rapide et sale, assez efficace, et utile dans la plupart des situations où je clonerais un simple hachage de propriétés.
Bonne réponse mais notez que "profond" est relatif. Il ne suivra pas les références à d'autres objets.
@djechlin Bien sûr que oui. Essayez-le : jsfiddle.net/katowulf/E5jC3 (testé avec le nœud 0.10.11). Il ne sera pas capable de reconstituer des fonctions ou des données prototypiques, mais il obtient les valeurs autour juste bien.
Il existe quelques modules Node si vous ne voulez pas "rouler vous-même". Celui-ci semble bon : https://www.npmjs.com/package/clone
Il semble qu'il gère toutes sortes de choses, y compris les références circulaires. De la github page :
clone maîtrise le clonage d'objets, de tableaux, d'objets Date et d'objets RegEx et 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. [...] Des références circulaires ? Oui !
Il est difficile de réaliser une opération de clonage générique mais utile car ce qui doit être cloné de manière récursive et ce qui doit être simplement copié dépend de la manière 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 la suivante
null
o undefined
renvoient simplement la même chose (le cas particulier est nécessaire parce que c'est une erreur d'essayer de voir si un clone
est présente)clone
puis utiliser cette méthodeCette 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 est juste une copie superficielle, vous pouvez appeler values.slice()
au lieu de clone(values)
.
Par exemple, dans le code ci-dessus, je demande explicitement que le clonage d'un objet polygone clone les points, mais partage le même objet de style. Si je veux cloner l'objet de style aussi, je peux simplement passer la directive clone(this.style)
.
+1 pour avoir mentionné que les objets doivent implémenter .clone
méthode eux-mêmes. C'est la meilleure façon de gérer le clonage des objets.
Il n'existe pas de méthode native pour cloner des objets. Underscore implémente _.clone
qui est un clone peu profond.
_.clone = function(obj) {
return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
};
Elle 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 existe de bonnes raisons d'éviter le clonage profond, car les fermetures ne peuvent pas être clonées.
J'ai personnellement posé une question sur deep cloning objects before
et la conclusion à laquelle je suis arrivé est que tu ne le fais pas.
Je recommande d'utiliser underscore
et c'est _.clone
mé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 unes des options : http://jsperf.com/shallow-copying
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.