请参见以下示例:
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 = {}
并不相同?
答案 0 :(得分:2)
下图中的每个矩形表示一个对象。
const obj = { a: {} }
在内存中创建对象{ a: {} }
,并将其引用分配给变量obj
。
let aOfObj = obj.a
会将内部对象a
的引用分配给变量aOfObj
。
由于aOfObj
和obj.a
引用了同一对象,因此更改aOfObj
引用的对象也将反映在obj.a
上,因为他们是同一个对象。
现在,当您执行aOfObj = {}
时,您正在创建一个新对象(在内存中)并将其引用分配给aOfObj
,因此obj.a
和aOfObj
指向不同的对象
注意:
变量和对象都存储在内存中。变量(上方的所有内容)都存储在stack上,而对象(上方的所有内容)都存储在heap上。
在使用原始值(例如数字,字符串等)时,变量存储在堆栈中,其值就是原始值本身。例如:let n = 5;
在堆栈上创建变量n
,并将其值设置为文字数5
。
当使用对象(对象,数组,类的实例等)时,变量存储在堆栈中,而对象存储在堆中(因为堆栈较小)和引用(地址)该对象在内存中的值)作为变量的值存储在堆栈中。例如:let o = {}
在堆栈上创建变量o
,在堆上创建对象{}
,并将堆栈上的o
的值设置为该对象的地址这是一个数字(最终使堆栈更小)。
在javascript中,与某些其他语言不同,变量本身无法被引用,只能引用作为对象的值,这就是javascript is not a pass-by-reference language的原因。