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
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!
simplified:
this is because in js:
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.erects.push(new Rect(x, 50, 100, [...c]));