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

JavaScript跨对象属性赋值:为何修改john.address.city会改变sherlock的城市值?

为什么输出结果是Malibu而非London

核心原因是JavaScript中对象类型的赋值是引用传递,和原始值的赋值逻辑有本质区别。

逐行拆解实际运行逻辑

  • 初始化sherlock对象时,堆内存会分别创建两个独立的对象实例:
    1. 第一层主对象:存储属性surname: 'Holmes'和address指针
    2. 第二层address对象:存储属性city: 'London'
      栈上的sherlock变量、sherlock.address属性,存储的都是对应堆内存对象的引用地址,不是对象实体本身。
  • 初始化john对象时,执行address: sherlock.address的过程,并没有把sherlock的address对象完整复制一份给john,而是把sherlock.address里存的堆内存地址,原样赋值给了john.address。这一步完成后,sherlock.address和john.address两个属性,会指向堆内存里同一个公共对象,不存在任何隔离。
  • 后续两行赋值的实际效果:
    • john.surname = 'Lennon':surname是字符串原始值,赋值时会直接把新值写在john自己的属性上,完全不会影响sherlock的surname属性——这也是造成认知偏差的原因:原始值的赋值确实是值拷贝,两个变量不会互相影响,但对象类型的赋值规则完全不同。
    • john.address.city = 'Malibu':这行代码会顺着john.address存的引用地址,找到堆内存里的公共address对象,把它的city属性值改成Malibu。因为sherlock.address也指向这同一个对象,所以最后读取sherlock.address.city时,拿到的自然是修改后的Malibu,而不是初始的London。

认知误区说明

你原本以为“address: sherlock.address是把sherlock的address值给john,两个对象不会互相干扰”,这个逻辑仅对字符串、数字、布尔值这类原始值成立。只要赋值的是对象类型,传递的就是对象的内存引用,相当于两个人持有同一套房屋的钥匙,不管谁进屋改动了陈设,另一人开门看到的都是改动后的状态,不存在两套独立房屋的隔离效果。
如果需要让两个对象的address完全独立,可以在赋值时主动拷贝生成新对象,比如写address: { ...sherlock.address },这样会生成一个全新的address实例给john,后续修改john的city属性就不会对sherlock造成影响。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.25 08:27:05