在数组中添加两个相同的行,而不是只修改其中的一行

时间:2019-07-01 08:20:22

标签: javascript

首先,我在数组中添加了两个相同的行,后来我只需要修改最后一个,向其中添加新属性。我这样做的方式:

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'; 
   }
}

但是问题在于if语句中的代码不仅修改了最后一行,而且修改了它的前一行,因此refund_status = 'refunded'被添加到最后一行和最后一行之前。为什么会发生这种情况,并且只能修改最后一行?

3 个答案:

答案 0 :(得分:1)

这是因为推入数组的对象是按引用传递的,而不是按值传递的,因此,当您更改原始对象时,将在数组中更改对它的两个引用,请参见以下示例:

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

为避免这种情况,您需要克隆对象的值以创建一个新对象。 This问题有一些解决方法,使用JSON.parseJSON.stringify是在没有外部库的情况下深度复制对象的最短方法,请参见以下示例:

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]);

答案 1 :(得分:1)

当您两次使用同一对象时,最好使用Object.assign()创建一个副本(在这种情况下为浅)。这样可以避免在您的情况下从多个变量或数组索引中引用同一对象。

例如 rows.push(new_row);

成为

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

答案 2 :(得分:1)

因为您正在更改object的属性,并且javaScript中的object是通过链接而不是单独的实例进行访问的。换句话说,您在内存中具有相同的对象,并且更改了它的属性。这意味着new_row是您创建并多次推送的对象,它是相同的。  您可以通过在第二次按下时复制它来避免它:

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

其中{ ...new_row }主要创建新副本。 当您执行rows[rows.length - 1].refund_status = 'refunded';时,倒数第二个将更改。

我建议的另一种解决方案更准确:

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});

    }
});