【发布时间】:2023-01-10 21:58:15
【问题描述】:
想象以下代表个人的对象数组。
let people = [
{
name: 'Alice',
age: 19
},
{
name: 'Bob',
age: 32
},
]
您需要遍历每个对象,并将人物的头发和眼睛颜色添加到他们的对象中。幸运的是,他们都有棕色的头发和淡褐色的眼睛,因此您的任务变得简单了。出于某种原因,您决定使用属性访问器对于爱丽丝和一个解构赋值对于鲍勃。最后,您记录结果。
for (let i = 0; i < people.length; i++) {
let person = people[i];
if (person.name === 'Alice') {
person.hair = 'brown';
person.eyes = 'hazel';
}
else if (person.name === 'Bob') {
let additionalInfo = {
hair: 'brown',
eye: 'hazel'
}
person = { ...person, ...additionalInfo }
}
}
people.forEach(person => console.log(person));
但是,新信息出现在爱丽丝的对象中,但不在鲍勃的对象中!
{ name: 'Alice', age: 19, hair: 'brown', eyes: 'hazel' }
{ name: 'Bob', age: 32 }
现在,我明白了为什么 Alice 的对象会更新:person.hair = 'brown' 被视为 people[i].hair = 'brown' 因为 person === people[i]。
我有点但不完全了解为什么这不适用于此示例中的 Bob。一方面,我们将 person 变量重新分配给 people[i] 以外的其他变量,从而丢失了引用,并且 person 在该次迭代后丢失,对 Bob 的对象没有任何更改。
另一方面,我最初的预期是对person 的更改会导致对people[i] 的更改,因为person === people[i]。因此,这里的修复是将 person = { ...person, ...additionalInfo } 换成 people[i] = { ...person, ...additionalInfo } 有点令人惊讶。
为什么会这样?是否有可能在 JS 中创建一个对象的“稳定引用”,以便对包含引用的变量的更改应用于它所引用的对象?
【问题讨论】:
-
person = ...表示您正在为局部变量person分配一个新值。这不会影响people[i]。 -
“......以及 Bob 的解构任务......”那不是解构赋值。恰恰相反,它是结构化使用扩展语法赋值(创建对象)。
-
你关于“稳定”参考的问题的答案是否定的。您不能将对象属性或变量作为另一个变量的别名。你可以使用像 C++ 这样的语言,因为你可以使变量成为显式引用类型,但你不能使用 JavaScript。
-
问题不在于解构赋值,问题在于您忘记了语法
{}是new Object()的简写。您正在创建一个新对象,并将其分配给变量person。所以现在person指向那个新对象而不是people[i] -
@Pointy 实际上,即使在 C++ 中,当他忘记执行类似
a = new X()的操作不会更改a先前指向的内容,而是将地址分配给一个新对象时,他也会遇到这样的代码问题.
标签: javascript javascript-objects