Resolvendo a questão específica
Você pode usar uma asserção de tipo para informar ao compilador que você conhece melhor:
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;
}
Clonagem
Lembre-se de que às vezes é melhor escrever seu próprio mapeamento - em vez de ser totalmente dinâmico. No entanto, existem alguns truques de "clonagem" que você pode usar que oferecem efeitos diferentes.
Usarei o seguinte código para todos os exemplos subseqüentes:
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'));
Opção 1: espalhar
Propriedades: Sim
Métodos: Não
Cópia Profunda: Não
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
Opção 2: Object.assign
Propriedades: Sim
Métodos: Não
Cópia Profunda: Não
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
Opção 3: Object.create
Propriedades: Herdado
Métodos: Herdado
Cópia Profunda: Raso Herdado (mudanças profundas afetam o original e o clone)
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
Opção 4: Função de cópia profunda
Propriedades: Sim
Métodos: Não
Cópia Profunda: Sim
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
?Operador da propagação 1.Use
O operador Spread pega todos os campos do obj1 e os espalha sobre o obj2. No resultado, você obtém um novo objeto com nova referência e os mesmos campos que o original.
Lembre-se de que é uma cópia superficial, significa que se o objeto estiver aninhado, seus parâmetros compostos aninhados existirão no novo objeto pela mesma referência.
2.Object.assign ()
Object.assign cria cópia real, mas possui apenas propriedades, portanto, as propriedades no protótipo não existirão no objeto copiado. Também é cópia rasa.
3.Object.create ()
Object.create
não está realizando clonagem real , está criando objeto a partir do protótipo. Portanto, use-o se o objeto deve clonar propriedades de tipo primário, porque a atribuição de propriedades de tipo primário não é feita por referência.As vantagens de Object.create são que quaisquer funções declaradas em protótipo estarão disponíveis em nosso objeto recém-criado.
Poucas coisas sobre cópia superficial
A cópia rasa coloca no novo objeto todos os campos do antigo, mas também significa que, se o objeto original tiver campos de tipo composto (objeto, matrizes etc.), esses campos serão colocados no novo objeto com as mesmas referências. A mutação desse campo no objeto original será refletida no novo objeto.
Talvez pareça uma armadilha, mas realmente a situação em que todo o objeto complexo precisa ser copiado é rara. A cópia rasa reutilizará a maior parte da memória, o que significa que é muito barato em comparação à cópia profunda.
Cópia profunda
O operador de propagação pode ser útil para cópias profundas.
O código acima criou uma cópia profunda do obj1. O campo composto "complexo" também foi copiado para obj2. O campo de mutação "complexo" não refletirá a cópia.
fonte
Object.create(obj1)
cria um novo objeto e atribui obj1 como o protótipo. Nenhum dos campos no obj1 é copiado ou clonado. Portanto, alterações no obj1 sem modificar o obj2 serão vistas, uma vez que essencialmente não possui propriedades. Se você modificar o obj2 primeiro, o protótipo não será visto para o campo definido, pois o campo do obj2 com o nome está mais próximo na hierarquia.let b = Object.assign({}, a);
Tente o seguinte:
É uma boa solução até que você esteja usando objetos muito grandes ou seu objeto tenha propriedades não serializáveis.
Para preservar a segurança do tipo, você pode usar uma função de cópia na classe da qual deseja fazer cópias:
ou de forma estática:
fonte
undefined
valor, pelo menos. seobjectToCopy = { x : undefined};
depois de executar seu códigoObject.keys(objectToCopy).length
é1
, enquantoObject.keys(copy).length
é0
.O TypeScript / JavaScript possui seu próprio operador para clonagem superficial:
fonte
É fácil obter uma cópia superficial com o "Object Spread" introduzido no TypeScript 2.1
este TypeScript:
let copy = { ...original };
produz este JavaScript:
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-1.html
fonte
Para clone profundo serializável, com Informações do tipo é,
fonte
JSON.stringify
clone
. :)undefined
valor. Veja meu comentário na resposta semelhante acima: stackoverflow.com/questions/28150967/typescript-cloning-object/…Minha opinião:
Object.assign(...)
apenas copia propriedades e perdemos o protótipo e os métodos.Object.create(...)
não está copiando propriedades para mim e apenas criando um protótipo.O que funcionou para mim é criar um protótipo usando
Object.create(...)
e copiando propriedades para ele usandoObject.assign(...)
:Portanto, para um objeto
foo
, faça clone assim:fonte
foo
o pai prototípico doclonedFoo
(novo objeto). Embora isso possa parecer bom, lembre-se de que uma propriedade ausente será pesquisada na cadeia de protótipos, portanto,const a = { x: 8 }; const c = Object.assign(Object.create(a), a); delete c.x; console.log(c.x);
imprime 8, enquanto deveria serundefined
! (Link REPL: repl.it/repls/CompetitivePreemptiveKeygen )foo
, ela aparecerá automaticamente paraclonedFoo
! por exemplo,foo.y = 9; console.log(clonedFoo.y)
será impresso em9
vez deundefined
. É muito provável que não seja o que você está pedindo!Você também pode ter algo parecido com isto:
Apenas certifique-se de substituir o
clone
método em todas asEntity
subclasses, caso contrário, você terminará com clones parciais.O tipo de retorno
this
sempre corresponderá ao tipo da instância.fonte
Adicione
"lodash.clonedeep": "^4.5.0"
ao seupackage.json
. Então use assim:fonte
Se você receber este erro:
Este é o script correto:
fonte
cloneObj[attribut] = this.clone();
? ou você quer dizer #cloneObj[attribut] = this[attribut].clone();
Eu me deparei com esse problema e, no final, escrevi uma pequena biblioteca cloneable-ts que fornece uma classe abstrata, que adiciona um método clone a qualquer classe que o estende. A classe abstrata empresta a Função de Cópia Profunda descrita na resposta aceita por Fenton, substituindo apenas
copy = {};
porcopy = Object.create(originalObj)
para preservar a classe do objeto original. Aqui está um exemplo de uso da classeOu você pode simplesmente usar o
Cloneable.clone
método auxiliar:fonte
Aqui está o meu mash-up! E aqui está um link StackBlitz para ele. Atualmente, ele está limitado a apenas copiar tipos simples e tipos de objetos, mas poderia ser modificado facilmente, eu acho.
fonte
typeof null
também é um objeto, portanto, a consulta deve serif (source[P] !== null && typeof source[P] === 'object')
. Caso contrário, seus valores nulos serão transformados em um objeto vazio.Desde que o TypeScript 3.7 é lançado, os aliases de tipo recursivo agora são suportados e isso nos permite definir uma
deepCopy()
função de segurança de tipo :Parque infantil
fonte
Para um clone simples do conteúdo do objeto de furo, simplesmente codifico e analiso a instância:
Enquanto eu altero os dados na árvore objectToClone, não há alterações no cloneObject. Esse foi o meu requisito.
Espero que ajude
fonte
undefined
valor. Veja meu comentário na resposta semelhante acima: stackoverflow.com/questions/28150967/typescript-cloning-object/…Acabei fazendo:
Porque:
do @Fenton deu erros de tempo de execução.
Versão datilografada: 2.4.2
fonte
Que tal o bom e velho jQuery ?! Aqui está o clone profundo:
fonte
Fiz uma facada na criação de um serviço genérico de cópia / clone que retém tipos para objetos aninhados. Gostaria de receber feedback se estou fazendo algo errado, mas parece funcionar até agora ...
fonte
No typeScript eu testei com angular, e está indo bem
fonte
Para clonagem profunda de um objeto que pode conter outros objetos, matrizes e assim por diante, eu uso:
Usar:
fonte
Você pode usar a atribuição de desestruturação com sintaxe de propagação :
fonte
Se você já possui o objeto de destino, não deseja criá-lo novamente (como se estivesse atualizando uma matriz), deverá copiar as propriedades.
Se você fez dessa maneira:
Louvor é devido. (veja o título "versão 2")
fonte