为什么更改对象引用的值实际上并未更改对象?

时间:2020-11-07 12:54:05

标签: javascript

请参见以下示例:

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 = {}并不相同?

1 个答案:

答案 0 :(得分:2)

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

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

const obj = { a: {} }

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

let aOfObj = obj.a

由于aOfObjobj.a引用了同一对象,因此更改aOfObj引用的对象也将反映在obj.a上,因为他们是同一个对象。

aOfObj.b = 4

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

aOfObj = {}

注意:

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

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

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

在javascript中,与某些其他语言不同,变量本身无法被引用,只能引用作为对象的值,这就是javascript is not a pass-by-reference language的原因。