Realmente depende do que você gostaria de clonar. Este é um objeto JSON verdadeiro ou apenas qualquer objeto em JavaScript? Se você quiser fazer qualquer clone, poderá ter alguns problemas. Qual problema? Explicarei abaixo, mas primeiro, um exemplo de código que clona literais de objeto, quaisquer primitivos, matrizes e nós DOM.
function clone(item) {
if (!item) { return item; } // null, undefined values check
var types = [ Number, String, Boolean ],
result;
// normalizing primitives if someone did new String('aaa'), or new Number('444');
types.forEach(function(type) {
if (item instanceof type) {
result = type( item );
}
});
if (typeof result == "undefined") {
if (Object.prototype.toString.call( item ) === "[object Array]") {
result = [];
item.forEach(function(child, index, array) {
result[index] = clone( child );
});
} else if (typeof item == "object") {
// testing that this is DOM
if (item.nodeType && typeof item.cloneNode == "function") {
result = item.cloneNode( true );
} else if (!item.prototype) { // check that this is a literal
if (item instanceof Date) {
result = new Date(item);
} else {
// it is an object literal
result = {};
for (var i in item) {
result[i] = clone( item[i] );
}
}
} else {
// depending what you would like here,
// just keep the reference, or create new object
if (false && item.constructor) {
// would not advice to do that, reason? Read below
result = new item.constructor();
} else {
result = item;
}
}
} else {
result = item;
}
}
return result;
}
var copy = clone({
one : {
'one-one' : new String("hello"),
'one-two' : [
"one", "two", true, "four"
]
},
two : document.createElement("div"),
three : [
{
name : "three-one",
number : new Number("100"),
obj : new function() {
this.name = "Object test";
}
}
]
})
E agora, vamos falar sobre os problemas que você pode ter ao começar a clonar objetos REAIS. Estou falando agora, sobre objetos que você cria fazendo algo como
var User = function(){}
var newuser = new User();
Claro que você pode cloná-los, não é um problema, todo objeto expõe a propriedade do construtor, e você pode usá-lo para clonar objetos, mas nem sempre funcionará. Você também pode fazer coisas simples for incom esses objetos, mas vai na mesma direção - problemas. Também incluí a funcionalidade de clone dentro do código, mas ela foi excluída por if( false )declaração.
Então, por que a clonagem pode ser uma dor? Bem, em primeiro lugar, todo objeto / instância pode ter algum estado. Você nunca pode ter certeza de que seus objetos não têm, por exemplo, uma variável privada, e se for esse o caso, ao clonar o objeto, você apenas quebra o estado.
Imagine que não há estado, tudo bem. Então ainda temos outro problema. A clonagem por meio do método "construtor" nos dará outro obstáculo. É uma dependência de argumentos. Você nunca pode ter certeza de que alguém que criou este objeto não o fez, algum tipo de
new User({
bike : someBikeInstance
});
Se for esse o caso, você está sem sorte, someBikeInstance provavelmente foi criado em algum contexto e esse contexto é desconhecido para o método de clone.
Então o que fazer? Você ainda pode fazer a for insolução e tratar tais objetos como literais de objetos normais, mas talvez seja uma ideia não clonar tais objetos e apenas passar a referência deste objeto?
Outra solução é - você pode definir uma convenção de que todos os objetos que devem ser clonados devem implementar essa parte por si próprios e fornecer o método de API apropriado (como cloneObject). Algo que cloneNodeestá fazendo pelo DOM.
Você decide.