meli02 meli02 - 1 month ago 27
TypeScript Question

Array Push Overwrite

A record has an old color/number and new properties, which can be changed. I want to loop through an array and check to see if the old and new values don't match. If they don't, I'd like to determine which property was changed (color/number), set that record's changed property, and push it to an array. If the record has changes for both color and number, I want a copy of each array entry with the different changed property.

I've tried a few different ways and the push is overwriting the changed property, no matter what I do. I've tried to use a local array and that didn't work out either. Here is an example.

export class Record {
id: string;
oldcolor: string;
newcolor: string;
oldnumber: string;
newnumber: string;
changed: string;
}




@Input() newrecords: Record[];
output: Record[] = [];

functionTest() {

for (let rec of this.newrecords) {


if (rec.newcolor != rec.oldcolor) {

rec.changed = "color";
output.push(rec);


}

if (rec.newnumber != rec.oldnumber) {

rec.changed = "number";
output.push(rec);

}


}
}


desired result
[{
id: 1;
oldcolor: red;
newcolor: red;
oldnumber: 6;
newnumber: 6;
changed: color;
},
{
id: 1;
oldcolor: red;
newcolor: red;
oldnumber: 6;
newnumber: 6;
changed: number;
}]

Answer

When you do output.push('rec') it does not place a copy of rec in the array; it places rec (or, more precisely, a reference to rec) in the array.

So in the case where both properties have changed, you set rec.changed to "color", then put a reference to rec in the array, then set rec.changed to "number", then put another reference to rec in the array. Everything is being done to a single object instance.

What you meant to do was have two objects, each with the same id, oldColor, newColor, oldNumber, and newNumber; but with different changed values. (Whether that's the most efficient approach may be open to debate, but that's what you've described as the desired outcome.) To do that, at some point you must make a copy of rec.

One way to do this (using vanilla javascript):

var copy = {
    id: rec.id,
    oldColor: rec.oldColor,
    newColor: rec.newColor,
    oldNumber: rec.oldNumber,
    newNumber: rec.newNumber,
    changed: rec.changed
}

You could do this before every push (and then push(copy) instead of push(rec)); or if that creates too many unneeded copies you could specifically see when you need two instances and make a copy only then.

Comments