【问题标题】:Why changing the value of an object reference doesn't actually change the object? [duplicate]为什么改变对象引用的值实际上并没有改变对象? [复制]
【发布时间】:2020-11-07 12:54:05
【问题描述】:

请看下面的例子:

const obj = { a: {} }
let aOfObj = obj.a
console.log(obj.a === aOfObj)
aOfObj.b = 4
console.log(obj.a.b === aOfObj.b)
aOfObj = {}
console.log(obj.a === aOfObj)

所以aOfObj 是对obj.a 的引用。将aOfObj.b 设置为4 证明了这一点。原始对象的obj.a.b 也已修改。那么为什么设置aOfObj = {} 与设置obj.a = {} 不一样呢?

【问题讨论】:

  • 为此,您需要 C++ 中所谓的双指针
  • 因为你改变了 aOfObj 引用的内容,你并没有改变 obj.a 引用的内容——它仍然引用了之前的对象。
  • “所以aOfObj 是对obj.a 的引用” - aOfObj 存储“地址”,其中obj.a 可以在内存中找到。 “那么为什么要设置aOfObj = {} ...” - 这只是在aOfObj 中存储另一个地址。
  • 这与 foo = 0; foo = 42; 的工作方式完全相同,您没有将 0 更改为 42,但您正在更改变量 foo 的内容

标签: javascript


【解决方案1】:

下图中的每个矩形表示一个对象。

const obj = { a: {} } 在内存中创建对象{ a: {} },并将其引用分配给变量obj

let aOfObj = obj.a 将内部对象a 的引用分配给变量aOfObj

由于aOfObjobj.a 引用的是同一个对象,更改aOfObj 引用的对象 也会反映在obj.a 上,因为它们是同一个对象。 p>

现在当您执行aOfObj = {} 时,您正在创建一个新对象(在内存中)并将其引用分配给aOfObj,因此obj.aaOfObj 指向不同的对象。

注意:

变量和对象都存储在内存中。变量(上方左侧的所有内容)存储在stack 中,而对象(上方右侧的所有内容)存储在heap 中。

当使用原始值(如数字、字符串等)时,变量存储在堆栈中,其值就是原始值本身。例如:let n = 5; 正在堆栈上创建一个变量n,并将其值设置为文字数字5

当使用对象(对象、数组、类的实例...)时,变量存储在堆栈中,而对象存储在堆中(因为堆栈更小)和引用(地址该对象在内存中的值)存储为堆栈上变量的值。例如:let o = {} 在堆栈上创建变量o,在堆上创建对象{},并将堆栈上的o 的值设置为该对象的地址,该地址是一个数字(最终保持堆栈更小)。

在 javascript 中,与其他一些语言不同,变量本身不能被引用,只有作为对象的值才能被引用,这就是为什么 javascript is not a pass-by-reference language

【讨论】:

  • 您为什么重新打开这个已经关闭的问题,因为您在自己的答案中引用了 one question 的欺骗?这并没有添加任何新内容。即使是这样,它也应该被添加到欺骗目标中。
  • @Andreas 我的错。我只访问了第一个 dupe target,发现它并没有真正回答 OP 的问题,而第二个 dupe target 有类似的措辞(两者都是关于传递引用,这不是 OP 所问的,因为引用传递通常与函数调用有关)所以我没有费心打开它。我错了。第二个欺骗目标与OP的问题完全相同。
猜你喜欢
  • 2020-01-11
  • 1970-01-01
  • 1970-01-01
  • 2011-09-04
  • 1970-01-01
  • 2018-04-02
  • 1970-01-01
  • 2015-06-18
  • 1970-01-01
相关资源
最近更新 更多