在迭代数组时尝试修改当前项时,修改失败。以下是示例代码。
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}]
为什么运行时的第一个脚本显示对象权限的修改,但是最终数组显示哪些包含修改后的对象不符合预期?
答案 0 :(得分:2)
对象总是通过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);
也会起作用,因为你在这里创建了新的对象实例,并使用仅标量属性来填充它。