为什么改变一个数组会改变另一个?

IT技术 javascript arrays
2021-03-03 21:19:41

考虑一下这段 javascript 代码:

var a = [1, 2, 3],
    b = a;

b[1] = 3;

a; // a === [1, 3, 3] wtf!?

为什么当我更新“b[1]”时“a”会改变?我已经在 Firefox 和 Chrome 中对其进行了测试。例如,这不会发生在一个简单的数字上。这是预期的行为吗?

var a = 1,
    b = a;

b = 3;

a; // a === 1 phew!
6个回答

它是同一个数组(因为它是一个对象,所以它是同一个引用),您需要创建一个副本来分别使用.slice()(它创建一个新数组,其中第一级的元素被复制),如下所示:

var a = [1, 2, 3],
    b = a.slice();

b[1] = 3;

a; // a === [1, 2, 3]
我一直使用 Array.concat
2021-04-23 21:19:41
@Juan - 我直接提供了一些最佳文档的链接以进行完整解释,不过在这里添加了更多内容。
2021-04-30 21:19:41
你应该解释你为什么使用 slice... 并提到副本只有一层深
2021-05-05 21:19:41
感谢 .slice() 解决方案!这将被大量使用:)
2021-05-07 21:19:41

因为“a”和“b”引用同一个数组他们没有两个;将“a”的值分配给“b”会将引用分配给数组,而不是数组副本

当您分配numbers 时,您正在处理原始类型。即使在 Number 实例上也没有更新值的方法。

您可以在 Date 实例中看到相同的“它们指向同一个对象”行为:

var d1 = new Date(), d2 = d1;
d1.setMonth(11); d1.setDate(25);
alert(d2.toString()); // alerts Christmas day

除了其他答案之外,如果您想要一个数组的副本,一种方法是使用 slice 方法:

var b = a.slice(0)
事实上,这是一个很棒的补充!
2021-05-02 21:19:41

所有 Javascript 对象都是通过引用传递的 - 您需要复制整个对象,而不是分配它。

对于数组,这很简单 - 只需执行以下操作:

var a = [1, 2, 3];
var b = a.slice(0);

whereslice(0)返回从偏移量0到数组末尾的数组。

此链接有更多信息。

值类型引用类型之间存在差异

基本上值类型直接存储在计算机“堆栈”上,这意味着您实际上拥有“值”而不是所谓的指针/引用。

另一方面,引用类型不保存对象/变量的实际值,而是指向(引用)可以找到值的位置。

因此,当您说“我的引用类型 B 指向引用类型 A 指向的内容”时,您实际上有两个变量指向同一方向,并且当您与它们中的任何一个交互并更改某些内容时,两者都将指向更改的位置,因为从一开始就指向同一个地方。

在您的另一种情况下,您说“嘿,将变量 A 中的值复制到变量 B”,因此您的值位于不同的位置,这意味着对其中任何一个的任何更改都不会影响另一个。

@Gareth,这不是我说的吗?赋值会复制值,因此当您更改它时,它不会影响“a”。
2021-04-23 21:19:41
只是为了纠正你的最后一点。当值为数字时,分配没有不同。第二个例子不同的原因是因为更改( b = 3) 是另一个赋值,之前它对原始对象进行了可变更改
2021-04-25 21:19:41
抱歉,是的,我在第一次阅读时的印象是,您将原始类型和其他对象作为右值进行了区分。我的错
2021-04-25 21:19:41