Search code examples
javascript

Why is all of my array items updated when I change one of them


Edit: Turns out I placed a var inside my array in a for loop, which creates references to that variable, not copies of it. When I then try to change the var inside the array, I change what it references to, so the change will happen for all other objects referencing to it as well

I have tried making a js animation, but I run into a problem when I want to change a array item inside a object, inside a array..

Here is a simplified demonstration of my problem:

function Rect(x, y, s, c) {
    this.x = x,
    this.y = y,
    this.s = s
    this.c = c;
}

function start() {
    let rects = [];
    let c = [0,0,0];
    let x = 0;

    for (i = 0; i < 10; i++) {
        rects.push(new Rect(x, 50, 100, c));

        x += 110;
    }

    document.getElementById("txt0").innerHTML = "Values before value change";
    document.getElementById("txt1").innerHTML = rects[0].c;
    document.getElementById("txt2").innerHTML = rects[1].c;

    // I change value in one of the array-elements
    rects[0].c[0] = 1;

    document.getElementById("txt3").innerHTML = "Values after value change";
    
    // Why is the value changed for all my array-elements?
    document.getElementById("txt4").innerHTML = rects[0].c;
    document.getElementById("txt5").innerHTML = rects[1].c;
    
}

window.onload = start;

I tried to rewrite a general simplified example to recreate the problem, but then I did not get the problem:

function My_constructor() {
  this.my_array = [0, 0, 0];
}


let my_objects = [];
for (i = 0; i < 10; i++) { my_objects.push(new My_constructor()); }



// Print object 0 and 1 from array
document.getElementById("txt1").innerHTML = my_objects[0].my_array;
document.getElementById("txt2").innerHTML = my_objects[1].my_array;

// Change parameter in one of the objects from the array
my_objects[0].my_array[0] = 1;

document.getElementById("txt3").innerHTML = my_objects[0].my_array;
document.getElementById("txt4").innerHTML = my_objects[1].my_array;

Does anyone know why this may be?


Solution

  • simplified:

    let a=[1,2,3]
    let b = a
    b[0] = 777
    console.log(a) // outputs [ 777, 2, 3 ]
    

    this is because in js:

    arrays are reference values, so when you try to copy it using the = it will only copy the reference to the original array and not the value of the array. To create a real copy of an array, you need to copy over the value of the array under a new value variable. That way this new array does not reference to the old array address in memory.

    the problematic operation is rects.push(new Rect(x, 50, 100, c));, the c is the same across loop iterations.

    so when changing it later on, you're affecting... all references to that memory space.

    either move the let c = [0,0,0]; statement into the loop, or clone it using the spread operator[...c], i.e rects.push(new Rect(x, 50, 100, [...c]));