You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript对象稳定引用问题:为何Bob的对象未被正确更新?

问题分析与解答

问题背景

假设有如下表示个人信息的对象数组:

let people = [
    {
        name: 'Alice',
        age: 19
    },
    {
        name: 'Bob',
        age: 32
    },
]

要求遍历每个对象,为其添加头发和眼睛颜色(均为棕色头发、淡褐色眼睛):对Alice使用property accessor(属性访问器),对Bob使用解构赋值,写出的代码如下:

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

但执行后仅Alice的对象更新,Bob的对象无变化:

{ 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]?JS中能否创建“稳定引用”,让变量的变更直接作用于原对象?

原因分析

1. Bob的对象未更新的核心原因

在JavaScript中,对象属于引用类型,变量存储的并不是对象本身,而是指向对象在内存中位置的引用(内存地址)。

  • 对于Alice的逻辑:person.hair = 'brown'是在修改引用指向的原对象的属性——此时person和people[i]指向同一个内存中的对象,所以修改属性后,数组里的对象自然会同步变化。
  • 对于Bob的逻辑:person = { ...person, ...additionalInfo }是创建了一个全新的对象,然后把person变量的引用从原来指向people[i]的对象,改成指向这个新对象。但数组people中的第i个元素(people[i])仍然指向原来的旧对象,所以数组里的Bob对象不会有任何变化。

简单来说:修改引用指向的对象的属性,会影响原对象;但给变量重新赋值一个新对象,只是改变了变量的指向,和原对象无关。

关于“稳定引用”的问题

JavaScript中不存在所谓的“稳定引用”——即无法让变量的重新赋值操作直接修改它原本指向的原对象。因为变量的引用本身是可以被覆盖的,这是JS语言的设计特性。

但可以通过以下方式实现类似的效果:

  • 直接操作数组元素:把person = { ...person, ...additionalInfo }改成people[i] = { ...person, ...additionalInfo },直接更新数组中存储的引用,这样数组里的元素就会指向新对象。
  • 修改原对象而非创建新对象:不用解构创建新对象,而是用Object.assign修改原对象的属性,比如:
    Object.assign(person, additionalInfo);
    
    这种方式和Alice的逻辑一样,是修改原对象的属性,自然会同步到数组中。
  • 用包裹对象间接实现:如果一定要通过变量赋值来影响原对象,可以把目标对象放在一个包裹容器(比如数组或另一个对象)里,修改包裹容器的属性:
    let wrapper = { obj: people[i] };
    wrapper.obj = { ...wrapper.obj, ...additionalInfo };
    people[i] = wrapper.obj;
    
    不过这种方式本质上还是绕不开直接更新数组的引用,实用性有限。

内容的提问来源于stack exchange,提问作者randomnoise132

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 12:02:17