为什么推送操作的结果会因目标嵌套数组的声明方式而出现奇怪的结果?

huangapple go评论65阅读模式
英文:

Why are funky results happening for push depending on how target nested array was declared?

问题

根据嵌套数组是直接声明还是使用new Array(length).fill([])声明,push方法的行为会有所不同。如果我改用concat方法,代码会返回预期的结果。

let sample = [0, 1, 2, 3];
let resultsA = [[],[],[],[]];
let resultsB = new Array(4).fill([]);
let resultsC = new Array(4).fill([]);

for (let i = 0; i < sample.length; i++) {
  resultsA[i].push(sample[i]);
  resultsB[i].push(sample[i]);
  resultsC[i] = resultsC[i].concat(sample[i]);
}

console.log("resultsA:");
console.log(resultsA);
console.log("resultsB:");
console.log(resultsB);
console.log("resultsC:");
console.log(resultsC);

结果A:数字被放置在正确的嵌套数组中。

结果B:所有的嵌套数组都被填充了样本数组的副本。

结果C:数字被放置在正确的嵌套数组中。

在控制台中,在推送/连接循环之前,这三个“results”数组似乎是等效的。

我知道.push会改变数组,而.concat不会,但这种行为似乎是由目标数组的声明方式导致的。

为什么会发生这种情况?

英文:

Depending on if a nested array is declared directly or with new Array(length).fill([]) I am getting strange behavior for push. If I instead use concat the code returns the expected result.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

let sample = [0, 1, 2, 3];
let resultsA = [[],[],[],[]];
let resultsB = new Array(4).fill([]);
let resultsC = new Array(4).fill([]);

for (let i = 0; i &lt; sample.length; i++) {
  resultsA[i].push(sample[i]);
  resultsB[i].push(sample[i]);
  resultsC[i] = resultsC[i].concat(sample[i]);
}

console.log(&quot;resultsA:&quot;);
console.log(resultsA);
console.log(&quot;resultsB:&quot;);
console.log(resultsB);
console.log(&quot;resultsC:&quot;);
console.log(resultsC);

<!-- end snippet -->

Result A: numbers are placed in correct nested array.

Result B: all nested arrays are filled with a copy of the sample array.

Result C: numbers are placed in correct nested array.

In the console all three 'results' arrays appear to be equivalent prior to the push / concat loop.

I know .push mutates and .concat does not, but this behavior seems to be resulting from how the target array was declared.

Why is this happening?

答案1

得分: 3

当你这样做:

new Array(4).fill([]);

你将相同的数组(理解为相同的引用)传递给数组的每个索引,因此当一个索引被更新时,你会在所有索引中看到更改,因为你实际上修改了每个索引所引用的数组。

所以,如果你想使用嵌套数组,你不应该使用fill方法(嵌套对象也会有相同的问题)。

英文:

When you do this :

new Array(4).fill([]);

You are passing the same array (understand same reference) to each index of the array, so when one index is updated you will see the changes in all the index because you actually modified the array every index refers to.

So if you want to use nested arrays you shouldn't use the fill method (and it would be the same problem with nested objects)

huangapple
  • 本文由 发表于 2023年7月17日 21:31:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/76704983.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定