【问题标题】:add properties to a JSON object during iteration?在迭代期间向 JSON 对象添加属性?
【发布时间】:2016-06-29 19:47:30
【问题描述】:

Mozilla 开发中心说:

最好不要在对象中添加、修改或删除属性 在迭代期间,当前访问的属性除外; 无法保证是否会访问添加的属性,

但是,直到以后我才需要访问添加的属性。那么添加它们是否安全?

例如

var animals = {"cats":25, "dogs":15}
for(var key in animals){
    if(key.substring(0,3) !=="big"){ // no danger of referencing them
        var newAnimal = "big" + key;
        animals[newAnimal] =0;
    }
} 

或者增加对象的大小会混淆“for - in”迭代?

【问题讨论】:

  • 您要为每个现有属性添加'big' 前缀吗?
  • 如果你遍历Object.keys(animals)返回的数组,你可以百分之一百地确定你新添加的属性不会被访问。顺便说一句,there's no such thing as a JSON object.
  • @RomanPerekhrest - 不,这只是一个简单的版本,实际对象包含游戏角色的详细信息。这些人中的许多人都离开了。该代码找到面向左侧的对象并使用面向右侧的数据创建类似的对象。然后游戏只从同一个集合中调用“左”或“右”(或顶部、底部等)。我发现这比在运行时不断改变方向要简单得多。

标签: javascript json object iteration


【解决方案1】:

文档没有说添加的属性不会被访问,他们说它是未定义的。

因此,根据实现的不同,您最终可能会得到 bigdogsbigbigdogs 等,从而导致无限循环。 或者它可能会做一些完全不同的事情,毕竟这是未定义的行为。

要解决此问题,请改为使用对象的副本并将新属性添加到副本中,而不改变循环对象。

编辑: 看起来您正在检查键是否以 big 开头,当我第一次查看时错过了它。所以你应该没事。

避免这样的未定义行为仍然是一种很好的做法。当将来某个时候必须更改代码并且循环/检查背后的原因并不完全清楚时,这很容易回来并咬你。

【讨论】:

  • 问题有if(key.substring(0,3) !=="big"){ // no danger of referencing them 正是为了避免这个问题。
  • @Oriol 是的,看看我的编辑——当我第一次查看 OP 的代码时错过了那一行。
【解决方案2】:

如果您不在乎“无法保证是否会访问添加的属性”,那么您可以这样做。

如果您想确保不会访问它们,请在循环之前对属性进行快照:

var animals = {"cats":25, "dogs":15}
for(var key of Object.keys(animals))
  animals["big" + key] = 0;
console.log(animals);

如果您想确保您会访问它们,请使用地图:

var animals = new Map([ ["cats",25], ["dogs",15]]);
for(var key of animals.keys())
  if(key.slice(0,6) !== 'bigbig')
    animals.set("big" + key, 0);
console.log([...animals].map(a => a.join(': ')));

【讨论】:

    【解决方案3】:

    是的,添加它们是安全的,因为您已经检查以确保您不会陷入无限循环。

    “添加”将其添加到随机位置,因此顺序不是您可以指望的,但看起来您不需要在同一循环中访问新创建的属性,这应该没问题。

    如果您只想添加新属性,我建议您创建一个新对象,该对象稍后将在您完成后替换当前对象。因为这样它会有更好的性能。

    也不会驱使正在审查您的代码的人发疯:)。祝你有美好的一天

    【讨论】:

      【解决方案4】:

      很安全

      开始迭代后,当

      • 在访问之前删除一个项目,你看不到它。
      • 更新一个项目,你会看到新值
      • 插入一个项目,您可能会或可能不会在当前循环中看到它。但这也是安全的。

      来源

      https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-03-01
        • 2016-12-30
        • 1970-01-01
        • 2021-03-19
        • 2016-01-07
        • 2017-02-10
        • 1970-01-01
        相关资源
        最近更新 更多