JavaScript:把数组推入另一个数组 vs. 把值推入数组?

3

我是一名新手,对JavaScript的push()方法不太了解。

我有两个空数组,row和newData。以下是两段代码,它们的输出结果非常不同:

for (i = 1; i <= 10 ; i++) {
    row[0] = i;
    newData.push(row);
}

在这种情况下,newData == [10,10,10,...,10],我觉得非常惊讶。
for (i = 1; i <= 10 ; i++) {
    newData.push(i);
}

结果是newData == [1,2,3,...,8,9,10],这是预期的结果。

但我不明白为什么第一个循环的每次迭代似乎都用最后一个元素替换了newData的每个元素,而第二个循环的工作方式却正常呢?

谢谢!


你如何显示你的结果?使用“alert”不是很可靠。请改用“console.debug”。 - stile17
可能是在javascript中按值复制数组的重复问题。 - hindmost
@stile17 我在jsfiddle中使用了一种技术,我在这里找到了https://dev59.com/2mQm5IYBdhLWcg3wug_S#20925259。我希望它是可靠的。编辑:我刚刚尝试使用firebug来显示console.log,确实更加精确。 - Alexandre d'Entraigues
3个回答

6

你的第一个片段:

var row = new Array();
var newData = new Array();

for (i = 1; i <= 10 ; i++) {
    row[0] = i;
    newData.push(row);
}

将引用推入数组row 10次,并同时依次更改该数组位置0中包含的值为1、2、3 .. 10,最终将row数组的内容设置为:[10]

实际的newData的最终值更正确地显示为:

[[10],[10],[10],[10],[10],[10],[10],[10],[10],[10]]

而不是:
 [10,10,10,...,10]

在JavaScript中,将一个对象(在这种情况下是Array类的一个实例)推入数组时,实际上是将对该对象的引用推入数组。将相同的变量row推入数组不会创建多个实例。
这种行为在这里得到了详细解释:JavaScript是按引用传递还是按值传递语言?

0

在你的第一个例子中,你将数组row连续十次推入newData。在每次迭代中,你还将值设置为i。在JavaScript中,数组是一个对象,当你推入它时,你是通过引用而不是值(这是在你的第二个例子中使用字面值的情况)。

因此,发生的情况是,你最终得到了一个数组newData,它有十个元素,都指向同一个JavaScript数组,即row。如果你改变row的第一个元素,row[0] = 2,那么newData也会反映这个变化。


好的,我现在明白了。所以在循环结束时,newData实际上是[row [0],row [0],... row [0]]而不是[10,10 ...,10]吗?还有一种方法可以推送row [0]的值而不是引用它吗? - Alexandre d'Entraigues
是的,没错。虽然当我运行你的代码时,整个 row 数组(一个单独的项)被推送了(正如 @Luigi Sgro 所说)。你可以通过推送运行 newData.push(row[0]) 来获得所需的行为,这将按值传递 row[0] 的值。 - Simon

0

第一个代码示例不会返回一个包含[10, 10, 10等]的数组,而是返回一个只有一个项目的数组:[10]。push方法基本上将每个对象添加到给定的数组中。如果给定的对象是一个数组,则它不会添加数组的项。它简单地像一个对象一样将其添加到数组中,并根据现有项确定索引。

另一种向数组添加项的方法是使用索引。以下是两个示例,它们都会得到相同的数组。

var arr = [];
for(var i = 0; i < 5; i++) {
    arr[i] = i;
}

[0, 1, 2, 3, 4]

var arr = [];
for(var i = 0; i < 5; i++) {
    arr.push(i);
}

[0, 1, 2, 3, 4]

希望这可以帮到你


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