【问题标题】:Change value of a nested key value in javascript在javascript中更改嵌套键值的值
【发布时间】:2019-04-27 21:46:48
【问题描述】:

我正在尝试更改嵌套键值结构中的特定值,但是当我设置一个值时,它会更改所有键的值。

初始数据为:

   const data = {
      "1.157685561": {
        "1222344": {
          "batb": [
            [0, 0],
            [0, 0],
            [0, 0]
          ],
          "batl": [
            [0, 0],
            [0, 0],
            [0, 0]
          ]
        },
        "1222345": {
          "batb": [
            [0, 0],
            [0, 0],
            [0, 0]
          ],
          "batl": [
            [0, 0],
            [0, 0],
            [0, 0]
          ]
        }
      }
    }

我想改变特定路径的值

    data['1.157685561']['1222344']['batl'][0] = [1,2]

但结果是错误的。因为它改变了:

  • data['1.157685561']['1222344']
  • data['1.157685561']['1222345']

最终结果:

    {
      "1.157685561": {
        "1222344": {
          "batb": [
            [0, 0],
            [0, 0],
            [0, 0]
          ],
          "batl": [
            [1, 2],
            [0, 0],
            [0, 0]
          ]
        },
        "1222345": {
          "batb": [
            [0, 0],
            [0, 0],
            [0, 0]
          ],
          "batl": [
            [1, 2],
            [0, 0],
            [0, 0]
          ]
        }
      }
    }

源码:https://playcode.io/301552?tabs=console&script.js&output

【问题讨论】:

  • 这将如何发生?你必须有一些你没有向我们展示的其他代码——这实际上不会发生。
  • 你是如何生成这个结构的?
  • 我猜你是你没有复制对象。所以他们保留参考。你能创建一个可运行的 sn-p 来显示问题吗?
  • 我确实添加了源代码
  • 检查这一行:for (const runner of runners) {data[runner] = marketData;}。由于marketDataobject,因此您存储了对同一个object 的多个引用。这是个问题。

标签: javascript arrays dictionary key-value


【解决方案1】:

查看provided code的这一部分:

function createEmptyMarketData(runners) {
    const data = {};
    const marketData = {
        batb: [
          [0, 0],
          [0, 0],
          [0, 0]
        ],
        batl: [
          [0, 0],
          [0, 0],
          [0, 0]
        ]
    };

    for (const runner of runners) {
        data[runner] = marketData;
    }

    return data;
}

使用for (const runner of runners) {data[runner] = marketData;} 您正在存储对同一对象的多个引用。这是个问题。

一种可能的解决方案是将marketData 更改为每次调用时都会生成新的object 的方法。示例:

function createEmptyMarketData(runners)
{
    const data = {};

    const marketData = () => ({
        batb: [[0, 0], [0, 0], [0, 0]],
        batl: [[0, 0], [0, 0], [0, 0]]
    });

    for (const runner of runners)
    {
        data[runner] = marketData();
    }

    return data;
}

新版本: https://playcode.io/301583?tabs=console&script.js&output

【讨论】:

    【解决方案2】:

    是的,@Shidersz 是对的。我还检查了,因为当我从 Node 终端尝试时,我看不到任何问题,因为您粘贴在问题中的对象是由函数创建的对象(所以它工作正常)。

    > const data = {
    ...       "1.157685561": {
    .....         "1222344": {
    .......           "batb": [
    .......             [0, 0],
    .......             [0, 0],
    .......             [0, 0]
    .......           ],
    .......           "batl": [
    .......             [0, 0],
    .......             [0, 0],
    .......             [0, 0]
    .......           ]
    .......         },
    .....         "1222345": {
    .......           "batb": [
    .......             [0, 0],
    .......             [0, 0],
    .......             [0, 0]
    .......           ],
    .......           "batl": [
    .......             [0, 0],
    .......             [0, 0],
    .......             [0, 0]
    .......           ]
    .......         }
    .....       }
    ...     }
    undefined
    > 
    > data['1.157685561']['1222344']['batl'][0] = [1,2]
    [ 1, 2 ]
    > 
    > data
    { '1.157685561':
       { '1222344': { batb: [Array], batl: [Array] },
         '1222345': { batb: [Array], batl: [Array] } } }
    > 
    > data['1.157685561']['1222344']['batl'][0]
    [ 1, 2 ]
    > 
    > data['1.157685561']['1222345']['batl'][0]
    [ 0, 0 ]
    > 
    

    我想,那会发生什么。最后,我检查了您创建 data 的代码。在那里,您为不同的键引用相同的对象。

    因此,更新单个就像影响其他人一样,但在内部它们只是对存储真实对象的同一内存位置的引用。

    这个What is the most efficient way to deep clone an object in JavaScript? 对你理解变量的深浅拷贝的概念非常有帮助。

    最后你可以在https://playcode.io/301586?tabs=console&script.js&output查看更新的代码。我刚刚复制了外部 ma​​rketData 并放置在 for 循环中。

    就是这样。非常感谢。

    【讨论】:

      猜你喜欢
      • 2020-11-19
      • 2021-04-14
      • 1970-01-01
      • 2018-05-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-17
      相关资源
      最近更新 更多