【问题标题】:filling a multidimensional array within "for" loop (javascript)在“for”循环中填充多维数组(javascript)
【发布时间】:2012-11-21 11:08:17
【问题描述】:

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

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]])。因此,Javascript 首先计算smallArr 值,然后才填充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]])。

为什么会这样?

【问题讨论】:

  • 在第一种情况下,对数组的相同引用被插入到 largeArr 中,因此第二次循环修改只会修改单个实际数组的内容,其引用在 largeArr 中插入两次.
  • 在测试这样的代码以使用开发人员工具在 javascript 中插入断点时,它可能会对您有所帮助。这样您就可以看到结果不是由于优化造成的,但如果您不知道指针是什么,我想它仍然会令人难以置信。

标签: javascript arrays optimization for-loop multidimensional-array


【解决方案1】:

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

largeArr[i] = smallArr

您正在分配一个指针。指针细分:

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

smallArr = [] 

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

【讨论】:

  • 是的。给OP,作为实验,赋值largeArr[0][0] = 3,然后查看largeArr的内容。
【解决方案2】:

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

通过在每个循环回合初始化smallArr,您可以创建新对象;所以largeArr 的每个属性都会指向一个不同的数组。顺便说一句,这是一个 assignment,而不是 declaration - 您会(并且应该)使用 var statement 将变量声明为本地(对函数而言)。

【讨论】:

    【解决方案3】:

    在最后一次迭代中

    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]];
    

    【讨论】:

      【解决方案4】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-12-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-04-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多