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

JavaScript中判断变量是否引用同一对象及扩展运算符拷贝疑问

关于JavaScript扩展运算符拷贝与引用判断的疑问

我是JavaScript新手,正在学习扩展运算符(spread operator)。之前了解到它对数组或对象的顶层元素是深拷贝,嵌套数组或对象是浅拷贝,于是写了测试代码,但实际输出和我想的不一样:copiedObject.name === originalObject.name输出true,而我预期是false。另外还有两个问题:

  • 怎么可视化代码里的引用逻辑?
  • 怎么在JavaScript里判断两个属性是否引用同一个对象?

测试代码

const originalObject = {
  name: 'Alice',
  address: {
    street: '123 Main St',
    city: 'Anytown',
  },
};

const copiedObject = { ...originalObject };

console.log(copiedObject.name === originalObject.name); // 预期输出false,实际输出true

originalObject.address.city = 'Newtown';

console.log(copiedObject.address.city); // 输出"Newtown"(修改影响了两个对象)
console.log(originalObject.address.city);

console.log(copiedObject.address === originalObject.address); // 输出true(是不是说明两者引用同一个对象?)

问题解答

1. 为什么copiedObject.name === originalObject.name输出true?

你对扩展运算符的拷贝逻辑理解有个小偏差:扩展运算符对顶层对象是创建新对象(深拷贝顶层容器),但顶层属性如果是原始值(字符串、数字、布尔、null、undefined、Symbol),是直接复制值,而不是创建新的引用。

字符串"Alice"是原始值,原始值在JavaScript里是存在栈内存中的,没有引用地址一说。copiedObject.name和originalObject.name都是值为"Alice"的原始值,===比较原始值时是看内容是否完全相同,所以结果是true。

而像address这种嵌套对象是引用类型,扩展运算符只是把原对象里address的引用复制给了新对象,所以两个对象的address指向同一个堆内存里的对象,修改其中一个的city,另一个也会跟着变。

2. 怎么判断两个属性是否引用同一个对象?

直接用===(推荐用===而非==)比较就行。对于引用类型(对象、数组、函数等),===比较的是它们在内存中的地址是否相同——如果返回true,就说明两个属性引用的是同一个对象,比如你代码里的copiedObject.address === originalObject.address返回true,就证明这俩指向同一个address对象。

3. 如何可视化代码逻辑?

  • 浏览器调试工具:用Chrome/Firefox的开发者工具,在代码里加断点,调试时查看变量的引用关系;也可以用内存快照功能,查看对象的引用链。
  • 手绘草图:自己画栈和堆的结构:栈里存变量和原始值,堆里存引用类型的对象。比如originalObject和copiedObject是栈里的两个变量,各自指向堆里的新对象;这两个新对象的name属性都对应栈里的"Alice";而它们的address属性都指向堆里同一个address对象。
  • 可视化工具:用本地或在线的JS可视化工具(这类工具能把代码转换成图形化的引用关系图,直观展示哪些变量指向同一个对象)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 14:00:10