为什么示例代码中的“ a.push(b)”更改为“ b”?

时间:2018-09-09 16:07:26

标签: javascript arrays

我正在尝试将值推入数组,但这会将值添加到两个数组ab中。如何确定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 />

2 个答案:

答案 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中有更多相关内容。