迭代时修改数组

Array modification while iteration

本文关键字:数组 修改 迭代      更新时间:2023-09-26

在迭代数组时尝试修改当前项时,修改失败。下面是示例代码。

var s_arr = [{a: 1, b: 2}, {a: 3, b: 4}, {a: 5, b: 6}];
var arr = [];
for(var i in s_arr) {
  if(s_arr[i].a == 5) {
    s_arr[i].b = 0;
    console.log('First modification: ' +JSON.stringify(s_arr[i]));
    arr.push(s_arr[i]);
    s_arr[i].b = 9;
    console.log('Second modification: ' +JSON.stringify(s_arr[i]));
    arr.push(s_arr[i]);
  }
}
console.log('Final: ' +JSON.stringify(arr));

运行上面的脚本node test.js之后,下面是结果。

First modification: {"a":5,"b":0}
Second modification: {"a":5,"b":9}
Final: [{"a":5,"b":9},{"a":5,"b":9}]

预期结果如下。

First modification: {"a":5,"b":0}
Second modification: {"a":5,"b":9}
Final: [{"a":5,"b":0},{"a":5,"b":9}]

然而,当在迭代时添加新对象时&分配当前项(对象)的每个值广泛有效。

var s_arr = [{a: 1, b: 2}, {a: 3, b: 4}, {a: 5, b: 6}];
var arr = [];
for(var i in s_arr) {
  if(s_arr[i].a == 5) {
    s_arr[i].b = 9;
    console.log('Second modification: ' +JSON.stringify(s_arr[i]));
    arr.push(s_arr[i]);
    var a = {};
    a.a = s_arr[i].a;
    a.b = 0;
    arr.push(a);
    var b = {};
    b.a = s_arr[i].a;
    b.b = 9;
    arr.push(b);
  }
}
console.log('Final: ' +JSON.stringify(arr));

以下是修改脚本的结果。

Final: [{"a":5,"b":0},{"a":5,"b":9}]

为什么运行时的第一个脚本显示对象权限的修改,而最后一个数组显示由修改后的对象组成的内容与预期不同?

JS中的对象总是通过引用传递的。

arr.push(s_arr[i]);不创建对象的副本,它只是在arr数组中保存对它的引用
所以在数组中也可以看到对象内部的任何更改。

您应该显式克隆对象以防止更改
例如,您可以使用serialize-deserialize对:

arr.push(JSON.parse(JSON.stringify(s_arr[i])));

您的

var a = {};
a.a = s_arr[i].a;
a.b = 0;
arr.push(a);

也会起作用,因为您在这里创建新的对象实例,并使用仅标量属性来填充它。