var arr = [{a: "one", b: "two"}];
/* in real code I have actual filter condition, but the filtered result
share some common properties with value */
var res = {
arr1: arr.filter(x => x),
arr2: arr.filter(x => x)
};
res.arr1.forEach(x => x.a = "a");
console.log(arr); //should print [{a: "one", b: "two"}]
console.log(res.arr1); //should print [{a: "a", b: "two"}]
console.log(res.arr2); //should print [{a: "one", b: "two"}]

如果我更改对象arr1
的{{1}}数组中的值,那么为什么更改也应用于res
和arr2
? res
创建新数组,然后不应用效果。
我在这里做错了什么?
答案 0 :(得分:5)
新数组中的每个元素都保留相同的对象引用,因此您需要克隆该对象。如果没有嵌套值,则可以使用Object.assign
和Array#map
方法。要进行更深入的克隆,您需要使用其他库或需要实现自己的自定义函数。
static const

仅供参考: What is the most efficient way to deep clone an object in JavaScript?
答案 1 :(得分:1)
原因是数组包含对象的引用,而不是它们的副本。因此,虽然filter确实返回一个新数组,但它们内部的对象仍然引用相同的对象。
因此,当forEach改变res.arr1中引用的对象时,它正在修改所有数组中的对象,因为它们都指向相同的引用。
希望这有帮助。
答案 2 :(得分:0)
数组中的项目是对象 - 它们是引用类型。意味着您只有一个对象,而休止符是对同一个对象的引用。因此,从一个引用更改它会影响另一个引用的结果读取。您需要从阵列中复制<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/layout5"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This is the text"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This is the text"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This is the text"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This is the text"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This is the text"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This is the text"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This is the text"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This is the text"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This is the text"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This is the text"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="last checking text"/>
</LinearLayout>
s。在这里,我使用property spreading来复制对象。
item
&#13;
答案 3 :(得分:0)
当你写:
xs = [
{ p : true },
{ p : false }
];
ys = xs.filter(
x => x.p
);
以下是它在内存中的样子:
xs { p : false }
\ /
[ 0 , 1 ]
\
{ p : true }
/
[ 0 ]
/
ys
正如您所说,.filter()
创建了一个新数组,这就是xs
和ys
链接到不同数组的原因。然后,由于xs[0].p
为真,它会复制xs[0]
并将其推送到新数组。您需要在此处实现的是xs[0]
是{ p : true }
的链接,它不是对象本身,而ys[0]
是此链接的副本。因此,xs[0]
和ys[0]
链接到同一个对象,如果您撰写xs[0].p = false
,则可以使用ys[0].p
阅读更新。
xs[0]
\
{ p : false }
/
ys[0]
如果你想避免这种情况,你必须复制对象本身:
function copy (x) {
var y = {}; // new object
for (var k in x) y[k] = x[k];
return y;
}
ys[0] = copy(ys[0]);
由于copy()
会返回一个新对象,xs[0]
和ys[0]
现在会链接到不同的对象,因此,对一个对象的更改不会影响另一个对象:
xs[0].p = true;
xs[0] --- { p : true }
ys[0] --- { p : false }
关于您的代码,arr[0]
是{ a: "one", b: "two" }
的链接,.filter()
创建新数组,其中包含指向同一对象的此链接的副本:
res.arr1[0]
\
\
arr[0] ----- { a: "one", b: "two" }
/
/
res.arr2[0]
同样,如果你想避免这种情况,你必须复制对象本身。但是,由于arr
可能包含多个对象,因此必须遍历数组以逐个复制每个对象。 .map()
非常适合这项工作:
res.arr1 = arr.filter(f).map(copy);
res.arr2 = arr.filter(f).map(copy);
res.arr1[0] --- { a: "one", b: "two" }
arr[0] -------- { a: "one", b: "two" }
res.arr2[0] --- { a: "one", b: "two" }
但要小心,对于嵌套对象来说,它有点棘手:
xs = [{ p: {} }]; // nested objects
ys = [copy(xs[0])];
在上述情况中,xs[0]
和ys[0]
不同,但xs[0].p
和ys[0].p
相同:
xs[0]
\
{ p }
\
{}
/
{ p }
/
ys[0]
在这种情况下,您必须制作对象的深层副本。这个功能可以解决这个问题:
function copyTree (x) {
if (x instanceof Array) {
var copy = [];
for (var i = 0; i < x.length; i++) {
copy[i] = copyTree(x[i]);
}
return copy;
} else if (x === Object(x) && typeof x !== "function") {
var copy = {};
for (var k in x) {
copy[k] = copyTree(x[k]);
}
return copy;
} else {
return x;
}
}
res.arr1 = arr.filter(f).map(copyTree);
res.arr2 = arr.filter(f).map(copyTree);
请注意,嵌套数组会出现同样的问题,因此上面的数组测试。