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

Javascript 为什么改变一个数组会改变另一个?,javascript,arrays,Javascript,Arrays,考虑一下这一点点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! 因为数组是对存储它们的实际位置的引用。因为“a”和“b”引用同

考虑一下这一点点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!

因为数组是对存储它们的实际位置的引用。

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

分配数字时,您处理的是基本类型。即使在数字实例上,也没有更新值的方法

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

var d1 = new Date(), d2 = d1;
d1.setMonth(11); d1.setDate(25);
alert(d2.toString()); // alerts Christmas day
它是同一个数组(因为它是一个对象,所以它是同一个引用),您需要创建一个副本来分别使用(这将创建一个新数组,其中第一级的元素被复制),如下所示:

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

b[1] = 3;

a; // a === [1, 2, 3]

除其他答案外,如果您想要阵列的副本,一种方法是使用切片方法:

var b = a.slice(0)

语句
x=y
是这里唯一的特殊语句,它的意思是“将变量
x
指向对象
y

几乎所有其他操作都是更改
x

b = a;
b[1] = 3;
因此,您的第一条语句将变量
b
指向数组(也称为
a


您的第二条语句更改了
b
(以及
a
)所指向的数组

分配数组不会创建新数组,它只是对同一数组的引用。当分配给新变量时,会复制数字和布尔值。

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

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

var a = [1, 2, 3];
var b = a.slice(0);
其中
slice(0)
返回从偏移量
0
到数组末尾的数组


有更多信息。

之间有区别

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

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

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


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

您应该解释为什么要使用切片。。。还要提到副本只是一个级别deep@Juan-我提供了一个链接,可以直接链接到一些最好的文档以获得完整的解释,但在这里添加了更多。感谢.slice()解决方案!这将被大量使用:)我一直使用Array.concatVariables是对其对象存储位置的引用,更重要的是here@Gareth我就是这么说的。。。数组是一个变量,当你使用数组时,你对数组的看法不是根据它们的存储方式,而是根据它们的使用方式(即作为变量)。请纠正你的最后一点。当值为数字时,赋值没有区别。第二个示例不同的原因是,更改(
b=3
)是另一个赋值,之前它对原始赋值进行了可变更改object@Gareth那不是我说的吗?赋值会复制值,因此当您更改它时,它不会影响“a”。对不起,是的,我在第一次阅读时得到的印象是,您将原语和其他对象区分为右值。我的错