TransWikia.com

¿Porqué no funciona copiar un array? Javascript

Stack Overflow en español Asked by ABO172013923 on August 22, 2020

Realizo una iteración con ciclo for, .push() a un array nuevo. Sin embargo, al final de la iteración se repite el mismo registro.

var myArray = [
    { actividad: 'Work', valor: 9 },
    { actividad: 'Eat', valor: 1 },
    { actividad: 'Commute', valor: 2 },
    { actividad: 'Play Game', valor: 1 },
    { actividad: 'Sleep', valor: 7 }
];
console.log(myArray);
console.log(myArray.length);

var nuevoArray = [];
var registro = { actividad: '', valor: 0 }

for (var i = 0;i < myArray.length; i++) {
    registro.actividad = myArray[i].actividad;
    registro.valor = myArray[i].valor;
    console.log(registro);
    nuevoArray.push(registro);
}

console.log(nuevoArray);
console.log(nuevoArray.length);

3 Answers

Lo que pasa es que en Javascript (así como en muchos otros lenguajes alto nivel), el operador de asignación (=) entre dos variable no asigna el valor de la variable derecha, si no su referencia a un espacio de memoria. Esto quiere decir que al cambiar cualquiera de las dos variables involucradas se cambiará el valor de ambas, debido a que ambas tienen como referencia la misma dirección de memoria.

Cada vez que defines a registro reescribes su valor dentro del array y por fuera del array. Por eso mismo, solo permanece el último valor, debido a que ese fue el último cambio.

let arr = [{foo: 0,bar: 1},{foo: 2,bar: 3},{foo: 4,bar: 5}];

let copy = [];
let aux = {foo: 0,bar: 0};
for (let i = 0;i < arr.length;i++) {
    aux.foo = arr[i].foo; /*Se reescribe foo de arr*/
    aux.bar = arr[i].bar; /*Se reescribe bar de arr*/
    copy.push(aux);
}

console.log(copy);

Tienes varias manera de evitar esto:

Si quieres tener una copia de los valores del array original puedes usar slice()

let arr = [{foo: 0,bar: 1},{foo: 2,bar: 3},{foo: 4,bar: 5}];

let copy = arr.slice(0,arr.length);

arr[0] = {foo: 6,bar: 7};
console.log(arr);
console.log(copy);

Sin embargo, los objetos del array van a seguir teniendo la referencia original. Si quieres hacer un deep copy puedes usar map().

let arr = [{foo: 0,bar: 1},{foo: 2,bar: 3},{foo: 4,bar: 5}];

let copy = arr.map((obj) => {
    return {foo: obj.foo,bar: obj.bar};
});

arr[0].foo = 6;
arr[0].bar = 7;
console.log(arr);
console.log(copy);

Espero haberte ayudado.

Answered by Gabitohh on August 22, 2020

Al copiarlo de esa forma estás haciendo una copia POR REFERENCIA, es decir al hacer nuevoArray.push(registro); estás apuntando registro nuevoArray a registro, por ende cuando registro cambia, también va a cambiar los valores que ingresaste en nuevoArray.

cámbialo por:

nuevoArray.push(JSON.parse(JSON.stringify(registro)));

Mira en el siguiente link: TrucoDeJson

"básicamente consiste en convertir un objeto en una cadena, copiar dicha cadena en la nueva variable, y reconvertir la cadena en objeto"

Answered by Byron2017 on August 22, 2020

si lo que queres es clonar un array, dejo 4 posibles formas de clonar y al final del código hago referencia a tú código y donde esta el problema.

var myArray = [
        {actividad: 'Work', valor: 9},
        {actividad: 'Eat', valor: 1},
        {actividad: 'Commute', valor: 2},
        {actividad: 'Play Game', valor: 1},
        {actividad: 'Sleep', valor: 7}
    ];

    var copia1 = myArray.slice();
    var copia2 = [].concat(myArray);
    var copia3 = [...myArray];

    var copia4 = [];
    Object.assign(copia4, myArray);

    console.log("Copia 1")
    console.log(copia1);
        console.log("Copia 2")
    console.log(copia2);
        console.log("Copia 3")
    console.log(copia3);
        console.log("Copia 4")
    console.log(copia4);
    
    //TU CODIGO
    var nuevoArray = [];
    //SI DECLARAS ESTE OBJETO POR FUERA DEL FOR ESTAS USANDO LA MISMA REFERENCIA DEL OBJETO EN LA FUNCION PUSH DE ARRAY.
//var registro = { actividad: '', valor: 0 }

for (var i = 0;i < myArray.length; i++) {
    //registro.actividad = myArray[i].actividad;
    //registro.valor = myArray[i].valor;
    //console.log(registro);
    
    //CREAMOS NUEVO OBJETO CADA VEZ QUE INTERACTUA EL FOR.
    var registro = { actividad: myArray[i].actividad, valor:          myArray[i].valor };
    //INSERTAMOS EL OBJETO.
    nuevoArray.push(registro);
}

        console.log("Copia 5")
         console.log(nuevoArray);

En los ejemplos el contenido de los array son objetos (array de objetos) y estos se pasan como referencia no por copia, cuando le cambias la propiedad a uno este cambia en todos. Ejemplo: copia1.valor=1000 en copia2,copia3, copia4 van a cambiar el valor a 1000. En el ultimo ejemplo (tu código modificado) esta insertando al array un nuevo objeto que no esta referenciado con MyArray y las variables asignadas a los objetos como actividad (string) valor (numeric) estos se pasan por copia y no por referencia. Resumiendo el ultimo codigo de ejemplo generas una copia no referenciada. Resumiendo tú código para generar una copia full no referenciada:

var nuevoArray = [];
myArray.forEach(function (el) {
    nuevoArray.push({actividad: el.actividad, valor: el.valor});
});

Answered by toto on August 22, 2020

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP