En Javascript las variables que apuntan a objetos son referencias, por lo que la asignación entre las mismas se hace de esta forma con lo que la modificación de una de estas variables afecta al resto de referencias. Por ejemplo:
var myObject = {
text: ‘Clonning Objects’
};
var mySecondObject = myObject;
mySecondObject.text = ‘Clonando Objectos’;
// saldrá una alerta con el texto ‘Clonando Objetos’ ya
// que las variables se asignan por referencia
alert(mySecondObject.text);
En el alert(...) saldrá el texto ‘Clonando Objetos’ ya que ambas variables apuntan a la misma zona de memoria, de ahí las referencias. Es debido a esto, y que en algunas ocasiones necesitas clonar un objeto, por lo que es necesario implementar una función que lo haga. Para ello tenemos esta función, que la he visto en StackOverflow aunque la he retocado un poco, que funciona perfectamente:
function clone(from) {
if(from == null || typeof from != “object”)
return from;
if(from.constructor != Object &&
from.constructor != Array)
return from;
if(from.constructor == Date ||
from.constructor == RegExp ||
from.constructor == Function ||
from.constructor == String ||
from.constructor == Number ||
from.constructor == Boolean)
return new from.constructor(from);
var to = {};
to = to || new from.constructor();
for (var name in from) {
to[name] = typeof to[name] == “undefined” ?
this.clone(from[name]) :
to[name];
}
return to;
}
Con esta función, el ejemplo anterior se convierte:
var myObject = {
text: ‘Clonning Objects’
};
var mySecondObject = clone(myObject);
mySecondObject.text = ‘Clonando Objectos’;
// saldrá una alerta con el texto ‘Clonning Objects’ ya que,
// aunque las variables se asignan por referencia, nuestra
// función ha clonado nuestro objecto con lo que son dos
// objetos distintos
alert(mySecondObject.text);
Y aquí el mensaje del alert(...) ya será ‘Clonning Objects’. Con esto ya podemos duplicar objetos… Pero, como no había quedado muy conforme con la solución seguí buscando, más por encontrar otro tipo de solución (no veo lógico que Javascript no tenga una forma nativa de clonar objetos) que por mejorar rendimiento. Y, aunque no encontré la forma nativa (creo que no la hay), sí encontré otra mucho más corta y más elegante:
function clone(o) {
return eval(uneval(o));
}
La función eval(...) coge un texto y lo evalúa como su fuese Javascript, de forma dinámica. Y, lógicamente, la función uneval(...) hace lo contrario: dado un código en Javascript —una clase, un array, etc.— lo convierte en el texto correspondiente, por lo que esta función lo que hace es convertir el objeto en texto y el texto generado otra vez en objeto, clonando así el objeto que se pasa como parámetro.
De estas dos formas, la segunda solución me parece más elegante —pocas cosas se consiguen en una sola línea de código—. El problema que puede existir es el rendimiento, ya que no he visto nada por ahí y yo tampoco he hecho pruebas, así que la decisión queda para cada uno. Yo he probado las dos y ambas funcionan sin problemas. Si alguien hace sus pruebas, que comente sus resultados.







Puag… ¿Había mencionado ya que Javascript da asco?
Hola Diego.
Muy buena la entrada que publicaste en su día. A mi me ayudó muchísimo.
Un saludo.
Excelente amigo, me funciono tu funcion para clonar.