Resolviendo el problema específico
Puede usar una aserción de tipo para decirle al compilador que conoce mejor:
public clone(): any {
var cloneObj = new (this.constructor() as any);
for (var attribut in this) {
if (typeof this[attribut] === "object") {
cloneObj[attribut] = this[attribut].clone();
} else {
cloneObj[attribut] = this[attribut];
}
}
return cloneObj;
}
Clonación
Tenga en cuenta que a veces es mejor escribir su propio mapeo, en lugar de ser totalmente dinámico. Sin embargo, hay algunos trucos de "clonación" que puedes usar que te dan efectos diferentes.
Usaré el siguiente código para todos los ejemplos posteriores:
class Example {
constructor(public type: string) {
}
}
class Customer {
constructor(public name: string, public example: Example) {
}
greet() {
return 'Hello ' + this.name;
}
}
var customer = new Customer('David', new Example('DavidType'));
Opción 1: propagación
Propiedades: Sí
Métodos: No
Copia profunda: No
var clone = { ...customer };
alert(clone.name + ' ' + clone.example.type); // David DavidType
//alert(clone.greet()); // Not OK
clone.name = 'Steve';
clone.example.type = 'SteveType';
alert(customer.name + ' ' + customer.example.type); // David SteveType
Opción 2: Object.assign
Propiedades: Sí
Métodos: No
Copia profunda: No
var clone = Object.assign({}, customer);
alert(clone.name + ' ' + clone.example.type); // David DavidType
alert(clone.greet()); // Not OK, although compiler won't spot it
clone.name = 'Steve';
clone.example.type = 'SteveType';
alert(customer.name + ' ' + customer.example.type); // David SteveType
Opción 3: Object.create
Propiedades: heredados
Métodos: Se hereda
profundo de copia: Shallow heredada (profundos cambios afectan tanto original y copia)
var clone = Object.create(customer);
alert(clone.name + ' ' + clone.example.type); // David DavidType
alert(clone.greet()); // OK
customer.name = 'Misha';
customer.example = new Example("MishaType");
// clone sees changes to original
alert(clone.name + ' ' + clone.example.type); // Misha MishaType
clone.name = 'Steve';
clone.example.type = 'SteveType';
// original sees changes to clone
alert(customer.name + ' ' + customer.example.type); // Misha SteveType
Opción 4: Función de copia profunda
Propiedades: Sí
Métodos: No
Copia profunda: Sí
function deepCopy(obj) {
var copy;
// Handle the 3 simple types, and null or undefined
if (null == obj || "object" != typeof obj) return obj;
// Handle Date
if (obj instanceof Date) {
copy = new Date();
copy.setTime(obj.getTime());
return copy;
}
// Handle Array
if (obj instanceof Array) {
copy = [];
for (var i = 0, len = obj.length; i < len; i++) {
copy[i] = deepCopy(obj[i]);
}
return copy;
}
// Handle Object
if (obj instanceof Object) {
copy = {};
for (var attr in obj) {
if (obj.hasOwnProperty(attr)) copy[attr] = deepCopy(obj[attr]);
}
return copy;
}
throw new Error("Unable to copy obj! Its type isn't supported.");
}
var clone = deepCopy(customer) as Customer;
alert(clone.name + ' ' + clone.example.type); // David DavidType
// alert(clone.greet()); // Not OK - not really a customer
clone.name = 'Steve';
clone.example.type = 'SteveType';
alert(customer.name + ' ' + customer.example.type); // David DavidType
cloned instanceof MyClass === true
?1.Utilice el operador de propagación
El operador de propagación toma todos los campos de obj1 y los extiende sobre obj2. En el resultado, obtienes un nuevo objeto con una nueva referencia y los mismos campos que el original.
Recuerde que es una copia superficial, significa que si el objeto está anidado, sus parámetros compuestos anidados existirán en el nuevo objeto con la misma referencia.
2.Object.assign ()
Object.assign crea una copia real, pero solo propiedades propias, por lo que las propiedades en el prototipo no existirán en el objeto copiado. También es una copia superficial.
3.Object.create ()
Object.create
no está haciendo una clonación real , está creando un objeto a partir del prototipo. Así que úselo si el objeto debe clonar propiedades de tipo primario, porque la asignación de propiedades de tipo primario no se realiza por referencia.Las ventajas de Object.create son que cualquier función declarada en prototipo estará disponible en nuestro objeto recién creado.
Pocas cosas sobre copia superficial
La copia superficial coloca en un objeto nuevo todos los campos del anterior, pero también significa que si el objeto original tiene campos de tipo compuesto (objeto, matrices, etc.), esos campos se colocan en un objeto nuevo con las mismas referencias. La mutación de dicho campo en el objeto original se reflejará en un objeto nuevo.
Puede parecer una trampa, pero la situación en la que todo el objeto complejo necesita ser copiado es rara. La copia superficial reutilizará la mayor parte de la memoria, lo que significa que es muy barata en comparación con la copia profunda.
Copia profunda
El operador de propagación puede ser útil para la copia profunda.
El código anterior creó una copia profunda de obj1. El campo compuesto "complejo" también se copió en obj2. El campo de mutación "complejo" no reflejará la copia.
fuente
Object.create(obj1)
crea un nuevo objeto y asigna obj1 como prototipo. Ninguno de los campos en obj1 se copia o clona. Por lo tanto, se verán cambios en obj1 sin modificar obj2, ya que esencialmente no tiene propiedades. Si modifica obj2 primero, el prototipo no se verá para el campo que defina ya que el campo de obj2 con el nombre está más cerca en la jerarquía.let b = Object.assign({}, a);
Prueba esto:
Es una buena solución hasta que esté utilizando objetos muy grandes o su objeto tenga propiedades no serializables.
Para preservar la seguridad de tipos, puede usar una función de copia en la clase de la que desea hacer copias:
o de forma estática:
fuente
undefined
valor, al menos. siobjectToCopy = { x : undefined};
luego de ejecutar su códigoObject.keys(objectToCopy).length
es1
, mientras queObject.keys(copy).length
es0
.TypeScript / JavaScript tiene su propio operador para la clonación superficial:
fuente
Es fácil obtener una copia superficial con "Object Spread" introducido en TypeScript 2.1
este TypeScript:
let copy = { ...original };
produce este JavaScript:
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html
fuente
Para clones profundos serializables, con información de tipo es,
fuente
JSON.stringify
clone
. :)undefined
valor. Vea mi comentario sobre la respuesta similar anterior: stackoverflow.com/questions/28150967/typescript-cloning-object/…Mi opinión sobre esto:
Object.assign(...)
solo copiamos propiedades y perdemos el prototipo y los métodos.Object.create(...)
no está copiando propiedades para mí y solo creando un prototipo.Lo que funcionó para mí es crear un prototipo usando
Object.create(...)
y copiando propiedades usandoObject.assign(...)
:Entonces, para un objeto
foo
, haga un clon como este:fuente
foo
ser el padre prototípico delclonedFoo
(nuevo objeto). Si bien esto puede sonar bien, debe tener en cuenta que se buscará una propiedad faltante en la cadena del prototipo, por lo queconst a = { x: 8 }; const c = Object.assign(Object.create(a), a); delete c.x; console.log(c.x);
imprime 8, ¡mientras que debería serloundefined
! (Enlace REPL: repl.it/repls/CompetitivePreemptiveKeygen )foo
, ¡aparecerá automáticamenteclonedFoo
! Por ejemplo,foo.y = 9; console.log(clonedFoo.y)
se imprimirá en9
lugar deundefined
. ¡Es muy probable que no sea lo que estás pidiendo!También puedes tener algo como esto:
Solo asegúrate de anular el
clone
método en todas lasEntity
subclases, de lo contrario terminarás con clones parciales.El tipo de retorno de
this
siempre coincidirá con el tipo de la instancia.fuente
Añadir
"lodash.clonedeep": "^4.5.0"
a tupackage.json
. Luego use así:fuente
Si obtiene este error:
Este es el script correcto:
fuente
cloneObj[attribut] = this.clone();
? o quieres decircloneObj[attribut] = this[attribut].clone();
Encontré este problema yo mismo y al final escribí una pequeña biblioteca cloneable-ts que proporciona una clase abstracta, que agrega un método de clonación a cualquier clase que la extienda. La clase abstracta toma prestada la función de copia profunda descrita en la respuesta aceptada por Fenton solo reemplazando
copy = {};
concopy = Object.create(originalObj)
para preservar la clase del objeto original. Aquí hay un ejemplo del uso de la clase.O simplemente podría usar el
Cloneable.clone
método auxiliar:fuente
Aquí está mi mash-up! Y aquí hay un enlace de StackBlitz . Actualmente está limitado a copiar solo tipos simples y tipos de objetos, pero podría modificarse fácilmente, creo.
fuente
typeof null
también es un objeto, por lo que la consulta debería serloif (source[P] !== null && typeof source[P] === 'object')
. De lo contrario, sus valores nulos se convertirán en un objeto vacío.Desde que se lanzó TypeScript 3.7, los alias de tipo recursivo ahora son compatibles y nos permite definir una
deepCopy()
función de tipo seguro :Patio de recreo
fuente
Para un clon simple del contenido del objeto del agujero, simplemente encadenar y analizar la instancia:
Mientras que cambio los datos en el árbol objectToClone, no hay ningún cambio en cloneObject. Ese fue mi requisito.
Espero que ayude
fuente
undefined
valor. Vea mi comentario sobre la respuesta similar anterior: stackoverflow.com/questions/28150967/typescript-cloning-object/…Terminé haciendo:
Porque:
de @Fenton dio errores de tiempo de ejecución.
Versión mecanografiada: 2.4.2
fuente
¿Qué tal el viejo jQuery? Aquí está el clon profundo:
fuente
Intenté crear un servicio genérico de copia / clonación que retiene los tipos de objetos anidados. Me encantaría recibir comentarios si estoy haciendo algo mal, pero parece funcionar hasta ahora ...
fuente
En typeScript pruebo con angular, y está funcionando bien
fuente
Para la clonación profunda de un objeto que puede contener otros objetos, matrices, etc., uso:
Utilizar:
fuente
Podría usar la asignación de desestructuración con sintaxis extendida :
fuente
Si ya tiene el objeto de destino, por lo que no desea crearlo de nuevo (como si actualizara una matriz), debe copiar las propiedades.
Si lo ha hecho de esta manera:
Se deben alabar. (mira el título "versión 2")
fuente