Cela dépend vraiment de ce que vous souhaitez cloner. S'agit-il d'un objet vraiment JSON ou de n'importe quel objet en JavaScript? Si vous souhaitez faire un clonage, cela pourrait vous causer des problèmes. Quel problème? Je vais l'expliquer ci-dessous, mais d'abord, un exemple de code qui clone les littéraux d'objet, les primitives, les tableaux et les nœuds 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";
}
}
]
})
Et maintenant, parlons des problèmes que vous pourriez rencontrer lorsque vous commencez à cloner des objets RÉELS. Je parle maintenant d'objets que vous créez en faisant quelque chose comme
var User = function(){}
var newuser = new User();
Bien sûr, vous pouvez les cloner, ce n'est pas un problème, chaque objet expose la propriété du constructeur et vous pouvez l'utiliser pour cloner des objets, mais cela ne fonctionnera pas toujours. Vous pouvez également faire simple for insur ces objets, mais cela va dans le même sens - problème. J'ai également inclus la fonctionnalité de clonage dans le code, mais elle est exclue par if( false )déclaration.
Alors, pourquoi le clonage peut être une douleur? Eh bien, tout d'abord, chaque objet / instance peut avoir un état. Vous ne pouvez jamais être sûr que vos objets n'ont pas par exemple de variables privées, et si tel est le cas, en clonant un objet, vous cassez simplement l'état.
Imaginez qu'il n'y a pas d'état, c'est bien. Ensuite, nous avons encore un autre problème. Le clonage via la méthode "constructeur" nous donnera un autre obstacle. C'est une dépendance d'arguments. Vous ne pouvez jamais être sûr que quelqu'un qui a créé cet objet n'a pas fait, une sorte de
new User({
bike : someBikeInstance
});
Si tel est le cas, vous n'avez pas de chance, someBikeInstance a probablement été créé dans un certain contexte et ce contexte est inconnu pour la méthode de clonage.
Alors que faire? Vous pouvez toujours faire une for insolution et traiter ces objets comme des littéraux d'objet normaux, mais peut-être que c'est une idée de ne pas cloner du tout de tels objets et de simplement passer la référence de cet objet?
Une autre solution est - vous pouvez définir une convention selon laquelle tous les objets qui doivent être clonés devraient implémenter cette partie par eux-mêmes et fournir la méthode API appropriée (comme cloneObject). Quelque chose de ce que cloneNodefait pour DOM.
Tu décides.