0

First, I am adding two same rows in array and later I need to modify only the last one, adding new property to it. The way I do that:

for(var index in arrayOne) {
   var arrayOneItem = arrayOne[index];
   var new_row = {
      address: arrayOne[index].address,
      date: arrayOne[index].date,
      category: arrayOne[index].category,
   };
   rows.push(new_row);
   if(arrayOne[index].refund_status == 'refunded') {
      rows.push(new_row);
      rows[rows.length - 1].refund_status = 'refunded'; 
   }
}

But the problem is that the code inside if statement does not only modify last row, but also the one before it, so the refund_status = 'refunded' is added both to the last and one before last row. Why is this happening and is there a way to modify the last row only?

Kamalesh M. Talaviya
  • 1,422
  • 1
  • 12
  • 26
niksrb
  • 459
  • 7
  • 25
  • **Aside note:** Avoid the use of operator `in` to iterate, sometimes the array which is an object, could contain additional properties which are not indexes. Instead, embrace the operator `for...of` statement. – Ele Jul 01 '19 at 08:22
  • @Ele Got it, what should I use instead? – niksrb Jul 01 '19 at 08:24
  • Please provide your arrayOne value – dganenco Jul 01 '19 at 08:25

3 Answers3

1

This is because the object you push into the array is passed by reference and not by value, thus when you change the original object you will change both references to it in the array, see example below:

let someArray = [];
let someObj = {foo: "bar"};
someArray.push(someObj);
someArray.push(someObj);
someArray[0].foo = "baz";
console.log(someArray[1]);

To avoid this, you would need to clone the values of the object to create a new one. This question has some ways to do so, using JSON.parse and JSON.stringify is the shortest way to deep-copy an object without an external library, see example below:

let someArray = [];
let someObj = {foo: "bar"};
someArray.push(someObj);
let newObj = JSON.parse(JSON.stringify(someObj));
someArray.push(newObj);
someArray[0].foo = "baz";
console.log(someArray[1]);
DaCurse
  • 795
  • 8
  • 25
1

When you are using the same object twice it's best to create a copy (shallow in this case) using Object.assign(). This will avoid referencing the same object from multiple variables or array indexes in your case.

eg. rows.push(new_row);

becomes

rows.push(Object.assign({}, new_row));

Jordan Maduro
  • 938
  • 7
  • 11
1

Because you are changing property of an object, and object in javaScript is accessed through a link not a separate instance. In another words, you have the same object in memory and you change its property. It means, new_row is object you create and push it several times, and it's the same. You can avoid it by copying it when pushing second times:

if(arrayOne[index].refund_status == 'refunded') {
      rows.push({ ...new_row });
      rows[rows.length - 1].refund_status = 'refunded'; 
   }

where { ...new_row } basically creates new copy. When you do rows[rows.length - 1].refund_status = 'refunded'; only second last will change.

Another solution i'd suggest is a bit more accurate:

const rows = []; // empty
const arrayOne = []; // SOME DATA HERE as I understand
const refundedStatus = ;

arrayOne.forEach(element=> {
    rows.push(element);

    if (value.refund_status === 'refunded') {
        rows[rows.length].refund_status = 'refunded'; 
        rows.push({ ...element});

    }
});