我正在尝试将值推入数组,但这会将值添加到两个数组a
和b
中。如何确定b
数组没有被修改?
var a=[[1]];
var b= [2];
document.getElementById("1").innerHTML="a[1] "+a[1];
document.getElementById("2").innerHTML="b "+b;
a.push(b);
document.getElementById("3").innerHTML="a[1] "+a[1];
document.getElementById("4").innerHTML="b "+b;
a[1].push([3]);
document.getElementById("5").innerHTML="a[1] "+a[1];
document.getElementById("6").innerHTML="b "+b+" < why did this value changed?";
<div id="1"></div>
<div id="2"></div><br />
<div id="3"></div>
<div id="4"></div><br />
<div id="5"></div>
<div id="6"></div><br />
答案 0 :(得分:6)
只需使用slice()
复制原始数组,而不传递引用。 Array.slice()
将返回从原始数组复制的新数组实例。
执行a.push(b);
时,您已将数组b
的引用插入到a
中。
现在,当您执行a[1].push([3]);
时,实际上是将数组[3]
插入到b
引用中,该引用位于数组a
的索引1处。这就是为什么您看到一个更改的值。
var a=[[1]];
var b= [2];
document.getElementById("1").innerHTML="a[1] "+a[1];
document.getElementById("2").innerHTML="b "+b;
a.push(b.slice());
document.getElementById("3").innerHTML="a[1] "+a[1];
document.getElementById("4").innerHTML="b "+b;
a[1].push([3]);
document.getElementById("5").innerHTML="a[1] "+a[1];
document.getElementById("6").innerHTML="b "+b+" < why did this value changed?";
<div id="1"></div>
<div id="2"></div><br />
<div id="3"></div>
<div id="4"></div><br />
<div id="5"></div>
<div id="6"></div><br />
注意:
对于对象引用(不是实际对象),slice将对象引用复制到新数组中。原始数组和新数组都引用同一对象。如果引用的对象发生更改,则更改对新数组和原始数组都是可见的。
对于字符串,数字和布尔值(不是字符串,数字和布尔对象),切片将值复制到新数组中。一个数组中的字符串,数字或布尔值的更改不会影响另一数组。
答案 1 :(得分:2)
执行a.push(b)
时,a[1]
在b
中获得值的副本,该副本是对数组的引用,而不是复制。所以你得到这个:
+−−−−−−−−−−−−+ a[Ref5845]−−−−>| (array) | +−−−−−−−−−−−−+ +−−−−−−−−−+ | 0: Ref9635 |−−−−>| (array) | | 1: Ref2235 |−−+ +−−−−−−−−−+ +−−−−−−−−−−−−+ | | 0: 1 | | +−−−−−−−−−+ | | +−−−−−−−−−+ +−>| (array) | | +−−−−−−−−−+ | | 0: 2 | | +−−−−−−−−−+ b[Ref2235]−−−−−−−−−−−−−−−−−−−−−+
(这些“ RefNNNN”值表示引用(有点像内存中数组的地址,尽管不是字面意义。)我们从不直接看到这些引用。)
因此,自然地,使用a[1]
还是b
都没关系,如果修改了它们都指向的数组的状态,则无论您可以浏览哪一个。
如果您要这么做,有很多方法复制:
a.push(b.slice()); // Just about all versions of JavaScript
// or
a.push(Array.from(b)); // Added in ES2015, easily polyfilled
// or
a.push([...b]); // Added in ES2015, not easily polyfilled
请注意,这是浅副本。如果数组包含对象/数组引用,则与a.push(b)
一样,复制引用而不是对象/数组。在this question's answers中有更多相关内容。