Miro Miro - 11 days ago 7
TypeScript Question

Javascript (Typescript) nested for-loop updating all elements, not just the inner loop

When using for-loop in Typescript, for some reason the for loop updates the whole array. Here is the code:

UpdatesToAllSelectedTabs() {

if (this.selectedOuterTabs[1]) {
this.outerTabs[1].InnerTabs = this.outerTabs[this.referencedOuterTab].InnerTabs;
for (let j = 0; j < this.outerTabs[1].InnerTabs.length; j++) {
this.outerTabs[1].InnerTabs[j].OuterTabId = this.outerTabs[1].Id;
}
}
}


The first version of the code had also the outer loop, but it also doesn't work proper with the fixed outer index ( in example above = 1).
What this piece of code does, is the following:

If selected,
copies the innerTabs from the referenced outerTab[0] to outerTab[1]. Which is ok.
Then,
it sets the ...innerTabs[j].OuterTabId from both outerTabs[1] and outerTabs[0] to the this.outerTabs[1].Id.

Can someone please explain what is happening here? Why are the outerTab[0] also updated?

Answer

From this line:

this.outerTabs[1].InnerTabs = this.outerTabs[this.referencedOuterTab].InnerTabs;

It seems that this.outerTabs[1] is referencing the same object as this.outerTabs[this.referencedOuterTab], so if you change one you change the other one as well.

A simpler example of the problem:

let arr1 = [{ key: "value1" }, { key: "value2" }, { key: "value3" }];
let arr2 = new Array(...arr1);

console.log(arr1[1]); // {key: "value2"}
console.log(arr2[1]); // {key: "value2"}

arr2[1].key = "value2.2"

console.log(arr1[1]); // {key: "value2.2"}
console.log(arr2[1]); // {key: "value2.2"}

(code in playground)

To fix that you need to assign different instances, for example using Object.assign:

this.outerTabs[1].InnerTabs = Object.assign({}, this.outerTabs[this.referencedOuterTab].InnerTabs);

In my example:

let arr1 = [{ key: "value1" }, { key: "value2" }, { key: "value3" }];
let arr2 = new Array(Object.assign({}, arr1[0]), Object.assign({}, arr1[1]), Object.assign({}, arr1[2]));

console.log(arr1[1]); // {key: "value2"}
console.log(arr2[1]); // {key: "value2"}

arr2[1].key = "value2.2"

console.log(arr1[1]); // {key: "value2"}
console.log(arr2[1]); // {key: "value2.2"}

(code in playground)