JavaScript:使用for循环将数组推入数组

11
请解释给我听。我试图用for循环创建一个数组的数组。但是当它没有工作时,我尝试简化代码以理解Javascript在做什么,但是简单的代码也不合理。
function test(){
    var sub_array = [];
    var super_array =[];
    for (var i=1;i<=3;i++){
        sub_array.push(i);
        super_array.push(sub_array);
    }
    alert(super_array);
}
我期望看到的是[1; 1,2; 1,2,3],但实际上得到的是[1,2,3; 1,2,3; 1,2,3]。如果我按索引循环并赋值,也会出现相同的情况。
6个回答

18

你总是将对同一个数组的引用推入超级数组中。

为了解决这个问题,你可以使用 slice()来克隆子数组,然后再将其推入超级数组中:

function test() {
    var sub_array = [];
    var super_array = [];
    for (var i = 1; i <= 3; i++) {
        sub_array.push(i);
        super_array.push(sub_array.slice(0));
    }
    alert(super_array);
}

编辑: 正如 Dan D. 在下面正确指出的那样,你也可以调用没有参数的 concat() 而不是 slice(0)。根据这篇文章,它更快(我没有自己测试过):

for (var i = 1; i <= 3; i++) {
    sub_array.push(i);
    super_array.push(sub_array.concat());
}

2
你为什么选择使用.slice(0)来复制数组,而不是使用.concat()呢?虽然后者可能更快,但我做的分析并不确定。 - Dan D.
1
有趣的是,根据这篇博客concat()更快。我会在我的回答中提到它。谢谢你的评论 :) - Frédéric Hamidi
1
这个解决方案确实让我免于抓狂。谢谢。 - Andy

6
当你推送“sub_array”时,你不是在推送它的副本。你最终会在“super_array”中得到三个相同的数组。(我应该说你正在推送一个对同一数组的引用。)
你可以这样做:
    // ...
    super_array.push(sub_array.slice(0));

复制文件。

3

了解一下,JavaScript中的数组、对象、函数等都是引用类型(只有数字(Int, Floats等)和字符串是按值传递的,这意味着值被复制/重复)!如果你有一个var a=[];,然后说var b=a并添加b.push("bla"),那么显示a,将显示“bla”条目,即使你将其添加到b中。换句话说;对于JavaScript来说,a和b就像妈妈冰箱上的便笺:“左边的三明治是给你的。”然后你知道要拿左边的而不是随便从冰箱里拿个三明治。她还可以在你家门口写另一个便笺(变量b),这样你就知道在赶时间时去哪里找三明治了。如果她把三明治粘在门上……那就很尴尬了。JS也认为这是一样的:)

所以,解决您的问题的方法如下:

function test(){
    var super_array =[];
    for (var i=1;i<=3;i++){
        var subarray=[];
        for (var u=1;u<=4-i;u++){
            sub_array.push(u);
            super_array.push(subarray);
        }
    }
    alert(super_array);
}

重新定义子数组会创建一个新引用。这样,变量b(房子门上的第二个符号)指向不同三明治的方向——也许是爸爸的三明治。
希望我能帮助你理解这个问题。

2
请注意,在for循环的每次迭代中,您都将同一个数组推入super_array中。请尝试使用以下方法:
function test(){
    var sub_array = [];
    var super_array =[];
    for (var i=1;i<=3;i++){
        sub_array = sub_array.slice(0,sub_array.length);
        sub_array.push(i);
        super_array.push(sub_array);
    }
    alert(super_array);
}

使用切片操作符+1,即使在克隆整个数组时也不需要传递任何参数 arr.slice() === arr.slice(0,arr.length)。 - wheresrhys

0
你添加到super_array的是同一个sub_array。所以为什么它必须不同呢?
你并没有创建一个新的数组然后推入super_array中。

0

sub_array 存储在 super_array 中作为一个引用,这意味着当你改变 sub_array 时,这个改变会反映在 super_array 中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接