JavaScript 对象 w/Async + forEach 循环 - 赋值问题

JavaScript Object w/Async + forEach Loop - problems with value assignment

我的目标是创建一个对象,'tallys,' 游戏中的每个用户都有一个键,分配给这些用户键的值是一个数组,代表游戏中每周赢得的美元值。首先,我为游戏中的每个用户分配一个长度为 26 的数组(代表游戏中的 26 周),其中 26 个“0”值代表每周开始时的 $0 值,代码如下:

    const maxWeek = 25;
    let weeks = [];
    for (let i=0; i < maxWeek+1; i++) {
      weeks.push(0)
    };
    let tallys = {};
    users.forEach(user => {
      tallys[user] = weeks;
    });

...结果是这样的对象:

tallys is  {
  michaeljpow: [
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0
  ],
  'Mr. Cheeseburger': [
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0
  ],
  'brewster.stanislaw': [
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0,
    0, 0
  ],
  ... etc
}

然后,我 运行 一个小的 for 循环来按周计算每个用户的总计...这里的 'j' 变量从第 1 周开始,循环 运行 玩了多少周就玩了多少周 运行,像这样:

for (let j=1; j<wk+1; j++) {
  let sums = await BonusEvents().where({week: j}).sum('dollars_total as d').groupBy('username').select('username');
  console.log('sums for week ', j, ' are ', sums);
 };

此时我的状态仍然很好——这让我得到了我想要的,两个不同的 'sums' 两个星期的数组,到目前为止在游戏中发生了:

sums for week 1 are  [
  { d: -4.27, username: 'Mr. Cheeseburger' },
  { d: -4.27, username: 'dannuzio' },
  { d: 11.29, username: 'james.johnsonf' },
  { d: -4.27, username: 'brewster.stanislaw' },
  { d: 16.47, username: 'eric.wj.clarke' },
  { d: -4.27, username: 'mikeduin' },
  { d: 11.29, username: 'BH84' },
  { d: -4.27, username: 'kevsims' },
  { d: 11.29, username: 'michaeljpow' },
  { d: 47.58, username: 'superbkn' },
  { d: -4.27, username: 'whpfwashington' },
  { d: -4.27, username: 'benjamininghram' }
]
sums for week 2 are  [
  { d: -1.41, username: 'benjamininghram' },
  { d: -1.41, username: 'BH84' },
  { d: -1.41, username: 'brewster.stanislaw' },
  { d: -1.41, username: 'dannuzio' },
  { d: -1.41, username: 'eric.wj.clarke' },
  { d: -1.41, username: 'james.johnsonf' },
  { d: -1.41, username: 'kevsims' },
  { d: -1.41, username: 'michaeljpow' },
  { d: -1.41, username: 'mikeduin' },
  { d: -1.41, username: 'Mr. Cheeseburger' },
  { d: 14.06, username: 'superbkn' },
  { d: -1.41, username: 'whpfwashington' },
]

这就是事情变得混乱的地方。我修改了之前的函数,每周在我的 'sums' 数组上执行一次 forEach,并设计修改 'tallys' 对象以修改分配给每周的数组位置,并为每个用户提供适当的美元值。 (另外,以免此处的 'j-1' 看起来令人困惑——那是因为我希望游戏周 1 分配给数组中的第 0 个位置而不是第一个位置):

  for (let j=1; j<wk+1; j++) {
      let sums = await BonusEvents().where({week: j}).sum('dollars_total as d').groupBy('username').select('username');
      sums.forEach(weekSum => {
        tallys[weekSum.username][j-1] = weekSum.d;
       console.log('tallys are ', tallys);
      })
    };

所以我在这里期望的是得到这样的结果:

tallys = {
mikeduin: [-4.27, -1.41, 0, 0, 0 ... etc],
superbkn: [47.58, 14.06, 0, 0, 0 ... etc],
... etc
}

... 为每个用户提供适当的值。然而!一旦所有循环等都完成,这就是我最终得到的理货对象:

tallys are  {
  michaeljpow: [
    -4.27, -1.41, 0, 0, 0, 0,
        0,     0, 0, 0, 0, 0,
        0,     0, 0, 0, 0, 0,
        0,     0, 0, 0, 0, 0,
        0,     0
  ],
  'Mr. Cheeseburger': [
    -4.27, -1.41, 0, 0, 0, 0,
        0,     0, 0, 0, 0, 0,
        0,     0, 0, 0, 0, 0,
        0,     0, 0, 0, 0, 0,
        0,     0
  ],
  superbkn: [
    -4.27, -1.41, 0, 0, 0, 0,
        0,     0, 0, 0, 0, 0,
        0,     0, 0, 0, 0, 0,
        0,     0, 0, 0, 0, 0,
        0,     0
  ],
   ...etc
}

.....等等,但对于每个用户。它一遍又一遍地为每个用户分配完全相同的值——它们最终都以 -4.27 和 -1.41 结束,只是因为那是循环的最后一个 'd' 值。

当我的代码中有 tallys[weekSum.username] 时,为什么它用最后一个相关值更新每个用户名,所以它应该只更新一个每次在理货对象中的用户名??

在此先感谢您的帮助!


编辑:再次感谢大家的帮助。 @Bergi 在评论中的回答是正确的。当我按照他的建议编辑创建 'tallys' 的初始代码时——一切正常。 @vothanhdat 的方法,我将其标记为建议的答案,我在其中克隆了初始的 'weeks' 数组也解决了这个问题。

let tallys = {};
users.forEach(user => {
  let weeks = [];
  for (let i=0; i < maxWeek+1; i++) {
     weeks.push(0)
  };
  tallys[user] = weeks;
});

您的问题是每个 tallys[user] 引用同一个 weeks 数组。

示例:

let a = [1,2,3]
console.log(a) // [1,2,3]
let b = a // now a & b is reference to the same array
b[0] = 100 
console.log(a) // [100,2,3]

所以解决方案是为每个用户克隆阵列周

const maxWeek = 25;
let weeks = [];
for (let i = 0; i < maxWeek + 1; i++) {
  weeks.push(0)
};
let tallys = {};
users.forEach(user => {
  tallys[user] = [...weeks] //Clone week array
});