Javascript 将对象的值指定给另一个对象时的奇怪行为
首先让我为我糟糕的英语和javascript技能道歉,我是一个初学者 这是我的问题:我想将源对象(words.wordFailed[tmp])的键和值复制到目标对象(words.wordsFailedOnly[counter]): 完成后,我将向目标添加一个新的键/值对:Javascript 将对象的值指定给另一个对象时的奇怪行为,javascript,Javascript,首先让我为我糟糕的英语和javascript技能道歉,我是一个初学者 这是我的问题:我想将源对象(words.wordFailed[tmp])的键和值复制到目标对象(words.wordsFailedOnly[counter]): 完成后,我将向目标添加一个新的键/值对: words.wordsFailedOnly[ counter ][ 'newKey' ] = tmp; 尽管我没有将新键分配给源对象,但在执行第一个foreach循环之后,我注意到源对象也有这个新键“newKey” 以下是
words.wordsFailedOnly[ counter ][ 'newKey' ] = tmp;
尽管我没有将新键分配给源对象,但在执行第一个foreach循环之后,我注意到源对象也有这个新键“newKey”
以下是完整的代码部分:
settings.languages.forEach( function( lang ) {
let counter = 0;
Object.keys( words.wordsFailed ).forEach( function ( tmp ) {
if ( words.wordsFailed[ tmp ][ lang ] > 0 ) {
counter++;
words.wordsFailedOnly[ counter ] = words.wordsFailed[ tmp ];
words.wordsFailedOnly[ counter ][ 'newKey' ] = tmp;
}
});
});
换句话说,使用console.log(words.words失败)
我注意到两个对象都被分配了“newKey”键。这是一个非常好的添加行为,在我的代码中,我只是为目标创建了newKey,我从来没有告诉过要将这个key添加到源对象中。我就是不明白发生了什么事。我怎样才能避免这种行为?我只需要目标对象中的newKey
如果你有主意,有人能帮忙吗
编辑以获取更多信息:
源目标包含的内容示例:
{deu: 3, id: 16, eng: 3}
目标经过foreach循环后包含的内容示例(这是预期结果):
在第二个foreach循环中,源还包含“newKey”键(这不是我所期望的。我不期望源具有“newKey”键):
目标的预期结果:
{deu: 3, id: 16, eng: 3, newKey: 10}
来源的预期结果:
{deu: 3, id: 16, eng: 3}
这不是奇怪的行为,尽管当你刚开始的时候,它肯定会显得很奇怪。发生的情况是,当您将
words.words失败[tmp]
分配给words.words失败[counter]
时,您不是在复制数据,而是在引用原始对象。当您更改该对象(添加新的键/值对)时,您只将其添加到一个对象,但有两个位置指向该对象:words.words失败[tmp]
和words.words失败[counter]
// In javascript, just because two objects have the same key/values, doesn't mean they are equal
const a = { foo: 1 }
const b = { foo: 1 }
a === b // false
// but if you assign an existing object to a new variable, it doesn't copy the object, so the reference is the same, and the equality test passes. They're equal because they are the same instance in memory.
const a = { foo: 1 }
const b = a
a === b // true
// The same thing is happening with your code
const obj = words.wordsFailed[tmp] // just for example
words.wordsFailedOnly[counter] = words.wordsFailed[tmp];
obj === words.wordsFailedOnly[counter] // true
obj === words.wordsFailed[tmp] // true
words.wordsFailedOnly[counter] === words.wordsFailed[tmp] // true
所以,任何时候你更新一个,你都会更新“其他”,因为这里没有其他对象,只有你开始使用的对象
好的,那你怎么解决这个问题呢?您需要创建对象的副本。您可以通过多种方式实现这一点,但在现代JavaScript中,最简单的方法如下,但请注意,这仅适用于平面对象(一级键值对,无嵌套)
现在,您已经创建了源对象的副本,当您向目标对象添加新键时,它不会更新源,因为它们现在位于内存中的不同对象
实际上有一个非常好的系列(不幸的是通过电子邮件),你可以查看。它深入探讨了这个问题。这是在JavaScript中如何工作的最好解释之一。将对象值分配给另一个变量或属性不会产生副本。你给同一个对象指定了一个引用。问题:-,解决方案:-,…
让我为我糟糕的英语道歉,然后是一本哈利波特书谢谢大家!你们都救了我的星期六!
{deu: 3, id: 16, eng: 3, newKey: 10}
{deu: 3, id: 16, eng: 3}
// In javascript, just because two objects have the same key/values, doesn't mean they are equal
const a = { foo: 1 }
const b = { foo: 1 }
a === b // false
// but if you assign an existing object to a new variable, it doesn't copy the object, so the reference is the same, and the equality test passes. They're equal because they are the same instance in memory.
const a = { foo: 1 }
const b = a
a === b // true
// The same thing is happening with your code
const obj = words.wordsFailed[tmp] // just for example
words.wordsFailedOnly[counter] = words.wordsFailed[tmp];
obj === words.wordsFailedOnly[counter] // true
obj === words.wordsFailed[tmp] // true
words.wordsFailedOnly[counter] === words.wordsFailed[tmp] // true
// using the spread operator syntax
words.wordsFailedOnly[counter] = { ...words.wordsFailed[tmp] }
// or you can do this
words.wordsFailedOnly[counter] = Object.assign({}, words.wordsFailed[tmp])