为什么JSON值更新深层复制几个键?

时间:2019-03-31 23:20:22

标签: javascript json

摘要:对JS对象(JSON格式)中的单个值的写操作会修改两个值。 (可能是副本还是参考错误)。

更新:JSFiddle与错误的基本版本:https://jsfiddle.net/J_withfeeling/vmhx95yL/

完整问题:

我想先准备一些数据客户端,然后再将其写入服务器。

我这样创建对象:

let number = {};
let category = {};
number = {
   "numbers":{
      "num1":0,
      "num2":0,
      "num3":0
   }
};
console.log(categories);//confirming that categories is "{"category1":true,"category2":true}"
for(let m in majorList){//initialize the JSON object
   category[m] = Object.assign({}, number);
}
data = {major};

我现在有一个很好的JS对象,它以JSON格式构造:

   {
   "category":{
      "category1":{
         "numbers":{
            "num1":0,
            "num2":0,
            "num3":0
         }
      },
      "category2":{
         "numbers":{
            "num1":0,
            "num2":0,
            "num3":0
         }
      }
   }

我现在可以正确地console.log(data)了,没有问题。

然后用一些JS我想更新“ num”值。我现在就这样做:

//some stuff up here to figure out which "category" and "number" to increment

      console.log(cat);
      console.log(num);
      console.log(JSON.stringify(data));
      data['category'][cat]['numbers'][num] = data['category'][cat]['numbers'][num] + 1;
      console.log(JSON.stringify(data));
//the above 5 lines are executed multiple times in a loop

我希望从那些console.log语句中打印出来的内容是这样的:

category1
num2
"myJSON":{
   "category":{
      "category1":{
         "numbers":{
            "num1":0,
            "num2":0,
            "num3":0
         }
      },
      "category2":{
         "numbers":{
            "num1":0,
            "num2":0,
            "num3":0
         }
      }
   }
}
"myJSON":{
   "category":{
      "category1":{
         "numbers":{
            "num1":0,
            "num2":1,
            "num3":0
         }
      },
      "category2":{
         "numbers":{
            "num1":0,
            "num2":0,
            "num3":0
         }
      }
   }
}

这实际上是打印出来的:

category1
num2
"myJSON":{
   "category":{
      "category1":{
         "numbers":{
            "num1":0,
            "num2":0,
            "num3":0
         }
      },
      "category2":{
         "numbers":{
            "num1":0,
            "num2":0,
            "num3":0
         }
      }
   }
}
"myJSON":{
   "category":{
      "category1":{
         "numbers":{
            "num1":0,
            "num2":1,
            "num3":0
         }
      },
      "category2":{
         "numbers":{
            "num1":0,
            "num2":1,
            "num3":0
         }
      }
   }
}

两个“ category”键中的“ num2”值都在最里面的for循环中一次传递。为什么?

诚然,在此代码片段上方还有很多其他内容,但是在stackoverflow问题中要包含很多内容。绝对可以肯定的是那4个console.logs()之间有一行代码。这5行是按原样复制的,我不知道一个写操作如何可以编辑JSON对象中的多个值。

2 个答案:

答案 0 :(得分:0)

执行category[m] = {score};时,您将创建一个具有单个属性的新对象,该属性每次都引用同一对象score。因此,当您更新score值之一时,您将全部更新,因为它们都引用同一对象。

您可以改为使用category = { score: {...score} },这将创建一个新对象。

答案 1 :(得分:0)

因此,@ charlietfl指出了问题所在,我想出了一个解决方法(如果不太优雅)。

发生的事情确实如@charlietfl和@leftclickben所建议的那样,正在使用传递引用来创建JS对象,因此该对象的多个部分具有相同的引用。因此,当一个值被更新时,具有相同引用的所有其他值也将被更新。

为解决此问题,我移动了这两行代码:

let number = {};
number = {
   "numbers":{
      "num1":0,
      "num2":0,
      "num3":0
   }
};

从循环的顶部到内部,恰好在

之前
category[m] = Object.assign({}, number);

这样,“数字”对象在循环迭代之间被销毁并重新创建,因此我们可以确定,下次使用它构建“类别”对象时,绝对是不同的引用。这消除了重复写入问题。我还用工作代码段更新了问题中的JSFiddle,并添加了一些注释,作为该解释的缩写。

如果您想发布更详细的答案,请再次向@charlietfl喊叫,我很乐意支持。

相关文章: Is JavaScript a pass-by-reference or pass-by-value language?(如@jhpratt所述)。 还发现这很有帮助:JavaScript: How to pass object by value?