摘要:对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对象中的多个值。
答案 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?