為什么第一次修改有效(當我重新分配物件的屬性時)而不是第二次修改(當我重新分配整個物件時)?
const arr1 = [
{ id: 1, value: 1 },
{ id: 2, value: 2 },
{ id: 3, value: 3 },
{ id: 4, value: 4 },
{ id: 5, value: 5 },
]
arr1.forEach((item, index) => {
if (item.id === 1) {
item.value *= 10 // modify success
}
});
console.log(arr1);
arr1.forEach((item, index) => {
if (item.id === 1) {
item = {id:6,value:6} // modify fail
}
});
console.log(arr1);
.as-console-wrapper { max-height: 100% !important; top: auto; }
uj5u.com熱心網友回復:
您的困惑是自然的,這與實際物件和變數之間的差異有關。
在您的 foreach 函式中,您有一個變數“item”,它指向您正在回圈的陣列中的物件。但是當你跑
item = {id:6,value:6}
您不是在修改物件,而是使變數“item”指向您剛剛創建的新物件。
如果要更改實際物件本身,可以通過逐個修改值或使用 Object.assign 從另一個物件復制來手動完成。

接下來讓我們更改val物件的欄位,即分配給bar. 我們注意到變化是由兩個變數反映的foo,bar這是因為兩個變數都參考同一個物件。
let foo = {id: 1,val: "foo"};
let bar = foo;
bar.val = "bar";
console.log(foo, bar);

接下來我們為 分配一個新物件bar。請注意,這不會影響foo參考的物件,bar現在只是參考不同的物件。
let foo = { id: 1, val: "foo" };
let bar = foo;
bar = { id: 1, val: "bar" };
console.log(foo, bar);

讓我們將其與forEach您問題中的示例聯系起來。因此,在回圈的每次迭代中,回呼函式中forEach的item引數都指向陣列中的一個物件,當您從此item引數更改欄位時,它會更改陣列中的物件,但是當您分配item給新物件時,它不會執行任何操作存盤在陣列中的物件。
如果你想用一個新的物件替換整個物件,你可以采取幾種方法,下面提到了其中的兩種:
- 查找存盤物件的索引并將其替換為新物件。
const arr = [{ id: 1, value: 1 }, { id: 2, value: 2 }, { id: 3, value: 3 }, { id: 4, value: 4 }, { id: 5, value: 5 }];
const index = arr.findIndex((obj) => obj.id === 3);
if (index !== -1) {
arr[index] = { id: 6, value: 6 };
}
console.log(arr);
- 另一種真正常見的方法是
map覆寫陣列并創建一個替換該物件的新陣列。
const arr = [{ id: 1, value: 1 }, { id: 2, value: 2 }, { id: 3, value: 3 }, { id: 4, value: 4 }, { id: 5, value: 5 }];
const newArr = arr.map((obj) => (obj.id === 3 ? { id: 6, value: 6 } : obj));
console.log(newArr);
uj5u.com熱心網友回復:
因為item是對當前正在迭代的物件的參考,所以修改參考將反過來修改原始物件(因此在您的第一個代碼示例中觀察到的行為)。在第二個中forEach,您只需將參考重新分配給一個全新的物件,這樣您就不能再修改您正在迭代的原始物件。
基本上,當您使用 回圈遍歷陣列時forEach, ,item是一個變數,其當前值是指向當前正在迭代的物件的參考/指標。修改此物件會修改原始物件(因為它只是一個參考,而不是實際的克隆物件)。但是,當您重新分配它時,該參考不再存在,因為item它有一個新值指向。你可以像這樣修改它,成功:
const arr1 = [
{ id: 1, value: 1 },
{ id: 2, value: 2 },
{ id: 3, value: 3 },
{ id: 4, value: 4 },
{ id: 5, value: 5 },
];
arr1.forEach((item, index) => {
if (item.id === 1) {
item.value *= 10 // modify success
}
});
console.log(arr1);
arr1.forEach((item, index) => {
if (item.id === 1) {
item.id = 6;
item.value = 6;
}
});
console.log(arr1);
.as-console-wrapper { max-height: 100% !important; top: auto; }
您也可以通過回圈遍歷您希望重新分配的每個屬性來動態執行此操作,如下所示:
const arr1 = [
{ id: 1, value: 1 },
{ id: 2, value: 2 },
{ id: 3, value: 3 },
{ id: 4, value: 4 },
{ id: 5, value: 5 },
];
arr1.forEach((item, index) => {
if (item.id === 1) {
item.value *= 10 // modify success
}
});
console.log(arr1);
arr1.forEach((item, index) => {
if (item.id === 1) {
let toConvert = { id: 6, value: 6};
Object.entries(toConvert).forEach(([k, v]) => item[k] = v);
}
});
console.log(arr1);
.as-console-wrapper { max-height: 100% !important; top: auto; }
uj5u.com熱心網友回復:
對于第一種情況,可以理解為:
const it = { value: 10 };
const item = it;
item.value = 11;
console.log(it); // item and it point to the same object, so the object's property value is modified
第二種情況:
const it = { value: 10 };
let item = it; // Here item and it refer to the same object
item = { value: 6 }; // But here item points to the new object (direct assignment), and it still points to the original object
console.log(item, it); // So it is still { value: 10 }, and item is already { value: 6 }
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/491989.html
標籤:javascript 数组 目的 foreach 对象
