3

似乎 JavaScript 试图以某种方式优化代码,所以如果我们想在循环largeArr中用改变的一维数组 ( ) 的值填充多维数组 ( )并使用以下代码:smallArr

largeArr = []
smallArr = []

for (i=0; i<2; i++)
{
    smallArr[0]=i
    smallArr[1]=2*i

    largeArr[i]=smallArr
}

我们得到了一个意想不到的结果:(largeArr=[[1,2],[1,2]]必须是[[0,0],[1,2]])。因此,JavascriptsmallArr首先计算值,然后才填充largeArr. 为了得到正确的结果,我们必须smallArr在循环中声明:

largeArr = []

for (i=0; i<2; i++)
{
    smallArr = []
    smallArr[0]=i
    smallArr[1]=2*i

    largeArr[i]=smallArr
}

然后它按预期工作(largeArr=[[0,0],[1,2]])。

为什么它会这样?

4

4 回答 4

4

因为指针,这就是原因。Javascript 以这种(而且只有这种)方式继 Java 和 C 之后。当你做作业时

largeArr[i] = smallArr

你正在分配一个指针。指针分解:

在 C 中(以及在较小程度上,Java 和 Javascript)你没有基本的数组类型——相反,一个数组指向内存中的一个空间,你可以用你想要的任何信息填充那个空间(或者更确切地说,你已经宣布)。指针在内存中的存在方式?一个四(或八,或二,取决于您的系统)字节内存地址,它告诉编译器/解析器从哪里获得适当的信息。所以,当你在那里做那个赋值时,你是在告诉它:“嘿,设置 largeArr[i] 等于 smallArr 的内存地址。” 因此,当您对 smallArr 进行更改时,每次取消引用数组时都会反映出来 - 因为它实际上是同一个数组。但是当你这样做时:

smallArr = [] 

在循环内部,您说的是“创建一个新数组,并将 smallArr 设置为等于该数组的地址。” 这样,阵列就保持分离。

于 2012-12-03T22:00:18.490 回答
0

使用该行largeArr[i]=smallArr,您将i属性设置为对smallArr. 你不要复制它。最后, 的所有属性都largeArr将指向同一个smallArr,您每次都覆盖了其中的值。

通过初始化smallArr每个循环转弯,您可以创建新对象;因此 的每个属性都largeArr将指向不同的数组。顺便说一句,它是一个赋值,而不是一个声明——你会(并且应该)用一个var语句将变量声明为本地(函数) 。

于 2012-12-03T22:02:22.627 回答
0

在最后一次迭代中

smallArr[0]=i
smallArr[1]=2*i  

(其中i=1)上面的代码转换为:

smallArr[0]=1
smallArr[1]=2

你的大数组就是这样:

[smallArr, smallArr]

这导致了意想不到的结果:

[[1, 2], [1, 2]]

在 javascript 中,对象是通过引用复制的(一种 c 样式指针)。
为了获得所需的结果,您必须按值复制数组,或在每个循环中分配不同的数组:

var largeArr = [];

for (i=0; i<2; i++)
   largeArr[i] = [[i, 2*i]];
于 2012-12-03T22:03:05.080 回答
0

当您像上面那样分配数组引用时,您并没有分配该数组的,而只是对该数组的引用

把它想象成一个指针。largeArr[0] 和 largeArr[1] 指向 smallArr,循环迭代只是简单地改变 smallArr 的内容。largeArr 被“指向”的东西没有改变。

于 2012-12-03T22:05:48.713 回答