首先,我在数组中添加了两个相同的行,后来我只需要修改最后一个,向其中添加新属性。我这样做的方式:
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'
被添加到最后一行和最后一行之前。为什么会发生这种情况,并且只能修改最后一行?
答案 0 :(得分:1)
这是因为推入数组的对象是按引用传递的,而不是按值传递的,因此,当您更改原始对象时,将在数组中更改对它的两个引用,请参见以下示例:
let someArray = [];
let someObj = {foo: "bar"};
someArray.push(someObj);
someArray.push(someObj);
someArray[0].foo = "baz";
console.log(someArray[1]);
为避免这种情况,您需要克隆对象的值以创建一个新对象。 This问题有一些解决方法,使用JSON.parse
和JSON.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});
}
});