skip to Main Content

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?

2

Answers


  1. Your let variables are outside of the for loop. that means you’re putting in the same memory reference when you generate a new class. Put the let c and let x values inside the for loop and it will behave as you expect it to.

    this works because let is block scoped, meaning the memory is released once you start a new iteration of the for loop.

    Good luck!

    Login or Signup to reply.
  2. 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]));

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search