miércoles, 19 de febrero de 2014

Copiar arreglos en Javascript

Hoy toca hablar de Javascript, hace un par de meses vengo trabajando intensivamente con este lenguaje y tengo algunas cosas que compartir, esta es una de ellas.
En JS siempre se trabaja pasando valores y no referencias excepto en el caso de arreglos, objetos o funciones. En general esto es útil y uno se acostumbra con el tiempo, pero cuando trabajas con objetos complejos que contienen arreglos de otros objetos te topas con unos cuantos problemas, sobre todo al momento de modificar o copiar un arreglo.

Si tenemos arreglos que contienen tipos primitivos hacer copias es simple, existen principalmente dos formas de hacer copias sin que los datos de ambos arreglos queden linkeados: usando el método slice() o el método concat(). Un pequeño ejemplo.

var arregloFuente = ['a','b','c','d','e'];

var arregloDestino = arregloFuente.slice(); 

var arregloDestino = arregloFuente.slice(0); 
o
var arregloDestino = arregloFuente.concat(); 

Estos mismos métodos también se pueden aplicar a arreglos de objetos, con la diferencia que en este caso los dos arreglos contendrán referencias a los mismos objetos, por lo que si modificamos algún objeto en un arreglo este cambio se verá en ambos. Esto puede ser útil para sincronizaciones, pero molesto a la hora de aplicar filtros o duplicar data para modificarla. A nuestros rescate llega jQuery con su método extend() que permite hacer copias "superficiales"( shallow) o "profundas"(deep) de arreglos. Con "superficiales" me refiero a copias que se hacen usando referencias y con "profundas" me refiero a copias usando valores; esto es que, si modificamos un objeto dentro de uno de los arreglos no afectaremos al otro. La sintaxis es la siguiente.

var arregloFuente = [{color: 'rojo', peso: 10},{color: 'verde', peso: 10},{color: 'rojo', peso: 20}, {color: 'amarillo', peso: 5}];

// Copia superficial (Shallow copy) 
var arregloDestino = jQuery.extend([], arregloFuente); 

// Copia en profundidad (Deep copy) 
var arregloDestino = jQuery.extend(true, [], arregloFuente); 

Me pasó recientemente que incluso el método extend() no me hizo una copia en profundidad de un arreglo el cual contenía entre sus propiedades otro arreglo con objetos, para este caso lo único que me quedó fue hacer un método propio que haga el copiado del arreglo. Como dato, el arreglo anidado era un objeto observable de knockout, creo que esto tuvo algo que ver con que no me haga la copia en profundidad bien.

Saludos,
Giank.

No hay comentarios:

Publicar un comentario