Javascript 在不同的时间分配给数组会产生不同的结果

Javascript 在不同的时间分配给数组会产生不同的结果,javascript,arrays,ecmascript-2017,Javascript,Arrays,Ecmascript 2017,我有两种不同的代码,它们略有不同,但会产生不同的结果: (async () => { const results = new Array(concurrentBrowsers).fill({}); const browsers = []; for (let index = 0; index < concurrentBrowsers; index++) { browsers.push( (async function() { let i

我有两种不同的代码,它们略有不同,但会产生不同的结果:

(async () => {
  const results = new Array(concurrentBrowsers).fill({});
  const browsers = [];
  for (let index = 0; index < concurrentBrowsers; index++) {
    browsers.push(
      (async function() {
        let i = index;
        const browser = await puppeteer.launch({ headless });
        const page = await getNewPage({ browser });
        results[i].loginPage = await timer(actions.loginPage, { page }); // <---- this line
        results[i].homePage = await timer(actions.homePage, {
          page,
          username,
          password
        });
        console.log(i, results[i]);
        browser.close();
      })()
    );
  }
  await Promise.all(browsers);
})();
还有一个:

(async () => {
  const results = new Array(concurrentBrowsers).fill({});
  const browsers = [];
  for (let index = 0; index < concurrentBrowsers; index++) {
    browsers.push(
      (async function() {
        let i = index;
        const browser = await puppeteer.launch({ headless });
        const page = await getNewPage({ browser });
        let loginPageTime = await timer(actions.loginPage, { page }); // <---- this line
        let homePageTime = await timer(actions.homePage, {
          page,
          username,
          password
        });
        results[i].loginPage = loginPageTime;
        results[i].homePage = homePageTime;
        console.log(i, results[i]);
        browser.close();
      })()
    );
  }
  await Promise.all(browsers);
})();
第一个代码中有一个bug,似乎
loginPage
结果总是取自上一次迭代,正如您所看到的,在所有迭代中都设置为相同的值

唯一的区别是,在第一个示例中,我将timer的结果分配给
results[I].loginPage
,在第二个示例中分配给
loginPageTime

有人能解释一下这种区别吗


谢谢

事实上,两种代码变体都有相同的问题,但第二个代码块没有显示出哪里出了问题:

const results = new Array(concurrentBrowsers).fill({});
这将创建一个(!)空对象并将其分配给所有数组项。您对该对象所做的任何更改都将通过所有数组条目看到,因为它们都引用同一个对象

您在第一个版本中看到不一致的原因是,在同一迭代中的两个
wait
表达式之间发生了其他赋值,而第二个代码版本直到
console.log
之前才进行赋值

您可以按如下方式正确初始化
结果

const results = Array.from(new Array(concurrentBrowsers), _ => ({}));

@Michael在每个数组项中都是相同的对象。。如。。就好像是你干的<代码>变量a={x:1},b=a;b、 y=2a和b都等于
{x:1,y:2}
IOW:javascript中的对象是基于引用的,当你复制引用时,不是复制引用的值。@Keith如果是这样,为什么loginPage是相同的,但是homePage不是?@Bob,因为请求是异步的,并且放在一个承诺内。所有,。。然后他一边走一边做控制台日志记录,这是一个时机问题。他的结果将取决于承诺何时兑现。。如果他在承诺之后做了
console.log(results)
,你会看到所有的值都是一样的。@trincot这很聪明,确实是个问题。我仍然不明白为什么这两种情况下的结果不同。也许这有助于理解在代码的第一个版本中(有问题的
results
initialization),您是否放置了
console.log(I,results[I])
在两次等待之间:然后您会注意到,记录的值通常与您从
控制台获得的输出不同。log
位于下面几行之后(对于相同的i)。这是因为第二个
wait
将允许解析其他承诺,并将其分配给
loginPage
,这将覆盖您刚才记录的值。FWIW,异步函数是ES2017的一项功能。
const results = new Array(concurrentBrowsers).fill({});
const results = Array.from(new Array(concurrentBrowsers), _ => ({}));