JavaScript 二维数组填充中的意外输出

Unexpected Output in JavaScript 2D Array Population

本文关键字:意外 输出 二维数组 填充 JavaScript      更新时间:2023-09-26

我有一个数组ele,我想用ele的副本填充另一个数组arr,然后返回填充的数组。 我拥有的JavaScript函数是:

function foo(n) {
    var arr = new Array(n);
    var ele = [0,1];
    for(var i=0;i<n;i++) {
        arr[i] = ele;
    }
    return arr;
}

例如 foo(3),我想要的输出是 [[0,1],[0,1],[0,1]] ,但我得到的输出是:[#1=[0, 1], #1#, #1#](使用 Firefox 的 Web 控制台(。 当我直接用 [0,1] 填充arr时,如

function fooNew(n) {
    var arr = new Array(n);
    for(var i=0;i<n;i++) {
        arr[i] = [0,1];
    }
    return arr;
}

我得到了fooNew(3)的正确输出:[[0,1],[0,1],[0,1]]。 为什么我的原始函数foo给出与fooNew相同的输出? 也就是说:为什么我不能通过将ele分配给arr[i]来填充arr,而必须通过将ele的内容直接分配给arr[i]来填充它,以获得我想要的输出?

===

===

更新:根据 Felix Kling 的有用答案,经过一些谷歌搜索,我发现通过使用 slice(0(,您可以将 ele 的副本放入 arr[i] 中,而不是引用它。因此,对foo的以下修改将给出所需的输出:

function foo(n) {
    var arr = new Array(n);
    var ele = [0,1];
    for(var i=0;i<n;i++) {
        arr[i] = ele.slice(0);
    }
    return arr;
}

实际上,Firebug的输出在这种情况下非常有用。它告诉您生成的数组的每个元素都引用同一个数组:

  [#1=[0, 1], #1#, #1#]
//  ^----------^----^  

#1(或#1#(是数组[0, 1]的占位符,表示引用。

它仍然是一个数组数组,只是Firebug的表示方式不同。

我不确定这是否是你想要的。例如,如果修改第一个数组的第一个元素:

result[0][0] = 5;

结果将是

[[5,1], [5,1], [5,1]]

我假设您希望数组彼此独立,因此每次都必须分配一个新数组。这就是您在第二种情况下所做的。


†:但它也提醒我们,一个人不应该总是相信他所看到的一切。例如,对象的状态可能与工具表示它的方式大不相同。这是一篇关于这种情况的文章(抱歉自我宣传(,该问题在Firebug中已修复,但在Chrome(afaik(中未修复。