Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/467.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 将对象的值指定给另一个对象时的奇怪行为_Javascript - Fatal编程技术网

Javascript 将对象的值指定给另一个对象时的奇怪行为

Javascript 将对象的值指定给另一个对象时的奇怪行为,javascript,Javascript,首先让我为我糟糕的英语和javascript技能道歉,我是一个初学者 这是我的问题:我想将源对象(words.wordFailed[tmp])的键和值复制到目标对象(words.wordsFailedOnly[counter]): 完成后,我将向目标添加一个新的键/值对: words.wordsFailedOnly[ counter ][ 'newKey' ] = tmp; 尽管我没有将新键分配给源对象,但在执行第一个foreach循环之后,我注意到源对象也有这个新键“newKey” 以下是

首先让我为我糟糕的英语和javascript技能道歉,我是一个初学者

这是我的问题:我想将源对象(words.wordFailed[tmp])的键和值复制到目标对象(words.wordsFailedOnly[counter]):

完成后,我将向目标添加一个新的键/值对:

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])