【问题标题】:Adding property in nested for-loop causes same values for each parent for-loop在嵌套的 for 循环中添加属性会导致每个父 for 循环的值相同
【发布时间】:2016-10-05 12:22:45
【问题描述】:

我有一个包含扑克牌信息的数组 (cardInfo)。在下面的代码中添加了一个数组示例。由于每张卡可能有重复,我想使用此信息通过将其信息推送到该类型的每张卡(属性“frequency1”)的新数组(drawPile)来创建一个套牌。

var common = 4;
var uncommon = 3;
var rare = 2;
var cardInfo = [
    {name:'Card A',frequency1:common,frequency2:rare,frequency3:0}, 
    {name:'Card B',frequency1:common,frequency2:uncommon,frequency3:0},
    {name:'Card C',frequency1:uncommon,frequency2:uncommon,frequency3:0}
];

var drawPile = [];
for (var cType = 0; cType < cardInfo.length; cType++) {
    for (var freq = 0; freq < cardInfo[cType].frequency1; freq++) {
        drawPile.push(cardInfo[cType]);
        console.log(drawPile.length - 1);
        drawPile[(drawPile.length - 1)].id = (drawPile.length - 1);
        console.log(drawPile[(drawPile.length - 1)]);
    }
}

然而,生成的控制台日志显示所有 4 张“卡 A”卡的 id 属性为 3,所有 4 张“卡 B”卡的 id 属性为 7,所有 3 张“卡 C”卡的 id 属性10. 就好像嵌套 (freq) 循环只对所有 .push() 命令运行,然后才添加 id 属性。

更奇怪的是:当我在jsfiddle 中运行此代码时,如果我先运行它然后打开控制台日志,我可以复制这些结果,但是当我在控制台 lof 已经打开后运行它时,它按预期工作.

如何确保每张卡都有唯一的标识符?

编辑:如果我创建一个全新的 for 循环专门用于添加 this code 中看到的 id 属性,当我得到完全相同的结果时,它会变得更加奇怪。

【问题讨论】:

  • @Gavin,这很奇怪。这是我第一次运行时的结果,稍后打开控制台:oi67.tinypic.com/2r2ureb.jpg
  • "所有 4 张“卡 A”卡的 id 属性为 3" - 当然有。它们都是同一个对象。您需要在循环中创建新对象以赋予它们不同的属性值。赋值不会复制对象。
  • @Bergi 每次将其推送到 drawPile 数组时,我不是都在创建一个新对象(尽管具有相同的属性和值)吗?
  • 不,你是在不断地推送对同一个对象的新引用。
  • 那么我该怎么做才能得到一个 drawPIle 数组,其中每个索引都包含一个具有唯一 id 属性的对象?

标签: javascript arrays object for-loop


【解决方案1】:

当您围绕cardInfo 集合循环时,对于每个cardInfo 实例,您都会围绕频率循环。从技术上讲,对于每个频率,您都在提取 cardInfo 的相同实例,因此从技术上讲,您正在为每个频率迭代更新相同的 cardInfo 实例。现在你的下一个语句将是,但我为每次迭代写console.log。但是当您调试代码时,console.log 输出正确,但是我不确定在没有调试的情况下是否会出现这种情况。那么如何解决这个问题呢?

在确定它为相关频率的每次迭代修改同一个实例后,我决定克隆卡(我并不是说这是一个好主意,但它证明了这个概念)。我通过使用实现了这一点:

JSON.parse(JSON.stringify(cardInfo[cType]));

同样,这不是实现这一目标的最有效方式,但突出了我认为问题所在。

我已将此更改应用于fiddle(我还稍微简化了代码),如果您删除克隆,它的运行方式与您当前看到的一样,但克隆后它会按您的预期工作。

希望对你有帮助

【讨论】:

    【解决方案2】:

    您正在循环中将对象引用推送到 drawPile 数组。这就是为什么所有“卡 A”卡都具有相同的 ID,因为数组包含相同的引用。在推入循环之前,您必须克隆对象。您可以对代码进行以下更改。

      for (var freq = 0; freq < cardInfo[cType].frequency1; freq++) {
                drawPile.push(JSON.parse(JSON.stringify(cardInfo[cType])));
                console.log(drawPile.length - 1);
                drawPile[(drawPile.length - 1)].id = (drawPile.length - 1);
                console.log(drawPile[(drawPile.length - 1)]);
            }
    

    【讨论】:

      猜你喜欢
      • 2021-02-28
      • 2015-01-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-11
      • 2013-10-26
      • 1970-01-01
      相关资源
      最近更新 更多