Si clono una matriz, uso cloneArr = arr.slice()
Quiero saber cómo clonar un objeto en nodejs.
Respuestas:
Para las utilidades y clases donde no hay necesidad de exprimir cada gota de rendimiento, a menudo hago trampa y solo uso JSON para realizar una copia profunda:
function clone(a) {
return JSON.parse(JSON.stringify(a));
}
Esta no es la única respuesta ni la más elegante; todas las demás respuestas deben considerarse para los cuellos de botella de producción. Sin embargo, esta es una solución rápida y sucia, bastante efectiva y útil en la mayoría de situaciones en las que clonaría un simple hash de propiedades.
newObj = obj.clone(args...);
Object.assign no se ha mencionado en ninguna de las respuestas anteriores.
let cloned = Object.assign({}, source);
Si está en ES6, puede usar el operador de propagación:
let cloned = { ... source };
Referencia: 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);
Hay algunos módulos de Node por ahí si no quiere "lanzar los suyos". Este se ve bien: https://www.npmjs.com/package/clone
Parece que maneja todo tipo de cosas, incluidas las referencias circulares. Desde la página de github :
clon maestros clonando objetos, matrices, objetos Date y objetos RegEx. Todo se clona de forma recursiva, por lo que puede clonar fechas en matrices en objetos, por ejemplo. [...] ¿Referencias circulares? ¡Sí!
Es difícil hacer una operación de clonación genérica pero útil porque lo que se debe clonar de forma recursiva y lo que se debe copiar depende de cómo se supone que funcione el objeto específico.
Algo que puede resultar útil es
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;
}
En este código la lógica es
nullo undefinedsimplemente devolver el mismo (el caso especial es necesario porque es un error intentar ver si un clonemétodo está presente)clonemétodo? entonces usa esoEsta función de clonación debería permitir implementar métodos de clonación personalizados fácilmente ... por ejemplo
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);
};
Cuando en el objeto sepa que una operación de clonación correcta para una matriz específica es solo una copia superficial, puede llamar en values.slice()lugar de clone(values).
Por ejemplo, en el código anterior, exijo explícitamente que una clonación de un objeto poligonal clone los puntos, pero compartirá el mismo objeto de estilo. Si también quiero clonar el objeto de estilo, simplemente puedo pasar clone(this.style).
.clonemétodo por sí mismos. Esta es la mejor forma de lidiar con la clonación de objetos.
if (x.clone)debería serif (typeof x.clone === 'function')
No existe un método nativo para clonar objetos. Subrayar los implementos _.cloneque es un clon superficial.
_.clone = function(obj) {
return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
};
O lo corta en rodajas o lo extiende.
Aquí está _.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 simplemente recorre todos los elementos y crea un nuevo objeto con los elementos que contiene.
Puede implementar su propia implementación ingenua si lo desea
function clone(o) {
var ret = {};
Object.keys(o).forEach(function (val) {
ret[val] = o[val];
});
return ret;
}
Hay buenas razones para evitar la clonación profunda porque los cierres no se pueden clonar.
Personalmente hice una pregunta deep cloning objects beforey la conclusión a la que llegué es que simplemente no lo haces.
Mi recomendación es el uso underscorey su _.clonemétodo para clones poco profundos.
Para una copia superficial, me gusta usar el patrón de reducción (generalmente en un módulo o similar), así:
var newObject = Object.keys(original).reduce(function (obj, item) {
obj[item] = original[item];
return obj;
},{});
Aquí hay un jsperf para un par de opciones: http://jsperf.com/shallow-copying
Antigua pregunta, pero hay una respuesta más elegante que la sugerida hasta ahora; use el utils._extend incorporado:
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 } }
Tenga en cuenta el uso del primer parámetro con un objeto vacío {} - esto le dice a extender que los objetos copiados deben copiarse en un nuevo objeto. Si utiliza un objeto existente como primer parámetro, el segundo (y todos los siguientes) parámetros se copiarán en profundidad sobre la primera variable de parámetro.
Usando las variables de ejemplo anteriores, también puede hacer esto:
var anotherMergeVar = { foo: "bar" };
extend(copiedObject, { anotherParam: 'value' }, anotherMergeVar);
console.log(copiedObject);
// outputs:
// { test: 12345, nested: { val: 6789 }, anotherParam: 'value', foo: 'bar' }
Utilidad muy útil, especialmente donde estoy acostumbrado a extenderme en AngularJS y jQuery.
Espero que esto ayude a alguien más; las sobreescrituras de referencias de objetos son una miseria, ¡y esto lo resuelve siempre!
Dependiendo de lo que quiera hacer con su objeto clonado, puede utilizar el mecanismo de herencia prototípico de javascript y lograr un objeto algo clonado a través de:
var clonedObject = Object.create(originalObject);
Solo recuerda que esto no es un clon completo, para bien o para mal.
Lo bueno de eso es que en realidad no ha duplicado el objeto, por lo que la huella de memoria será baja.
Sin embargo, algunas cosas difíciles de recordar sobre este método es que la iteración de las propiedades definidas en la cadena del prototipo a veces funciona de manera un poco diferente y el hecho de que cualquier cambio en el objeto original afectará al objeto clonado también a menos que esa propiedad también se haya establecido en sí mismo. .
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";uno, por supuesto, debe tener en cuenta que los cambios en el objeto original se reflejarán en el "clon" y que los cambios en el "clon" no se reflejarán en el objeto original, pero yo no lo llamaría peligroso - todo depende de lo que quieras hacer con tu clon
Implementé una copia profunda completa. Creo que es la mejor opción para un método de clonación genérico, pero no maneja referencias cíclicas.
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
Este código copia objetos con sus prototipos, también copia funciones (puede ser útil para alguien).
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;
}
Con esta copia no puedo encontrar ninguna diferencia entre el original y el copiado, excepto si el original usó cierres en su construcción, así que creo que es una buena implementación.
Espero que ayude
Los objetos y las matrices en JavaScript usan llamadas por referencia, si actualiza el valor copiado, podría reflejarse en el objeto original. Para evitar esto, puede clonar en profundidad el objeto, para evitar que se pase la referencia, utilizando el comando de ejecución del método cloneDeep de la biblioteca lodash
npm instalar lodash
const ld = require('lodash')
const objectToCopy = {name: "john", age: 24}
const clonedObject = ld.cloneDeep(objectToCopy)