我试图想象Javascript对象如何放在内存中的方式。由于它是一个对象,它存储在内存的堆部分。它也是键值对的集合。
现在,我有一个问题,Javascript对象是作为链表结构实现的吗?或者是别的什么?
在这里,我制作了一张从这段代码映射到内存的图片:
var o = {}
var o1 = { a: 1, b: o }
所以,关注o1
,有一个内存段,它引用了值1
,我们将该空间命名为a
。此外,属性b
具有另一个对象的地址。
我的问题是:这是映射到内存中的Javascript对象的准确表示吗?如果没有,我错过了什么?
基本的,我认为你的图表基本上是正确的,至少在主要思想中,对象是一个已定义的内存区域,其中包含其属性的插槽。
实际的内存结构不是由规范定义的,可以从JavaScript引擎到JavaScript引擎。
规范has to say是什么
Object在逻辑上是属性的集合。
...像a
和b
这样的数据属性有一个名称和值。 1是值,对象是值(稍后更多)。该规范没有涉及如何从各个地方引用值的问题。
实际的现代JavaScript引擎创建动态类以优化属性访问,因为属性访问是一种非常常见的操作。它们还通过对象引用处理对象,对象引用是指实际对象在引用的内存中的其他位置的值。在现代引擎中,你的对象很可能是用a
和b
的内存插槽实现的,两者的大小都可能是64位(但我不知道,这可能会有所不同),并且值1直接存储在插槽和b
的对象引用(再次指向内存中其他位置的对象)也直接存储在插槽中。细节因发动机而异。
因此,例如,您的代码很可能在内存中创建类似的内容(省略了很多细节):
+−−−−−−−−−−+ o: Ref33454−−−−−−−−−−−−−−−−−−−−−−+−>| (Object) | | +−−−−−−−−−−+ | +−−−−−−−−−−+ | +−−−−−−−−−−−−−−+ | o2: Ref54612−−−>| (Object) | | +−−−−−−−−−−−−−−+ | | a: 1 | | | b: Ref33454 |−+ +−−−−−−−−−−−−−−+
边注:
由于它是一个对象,它存储在内存的堆部分。
这不是一个有效的假设。例如,如果在函数中发生这种情况,并且该函数被充分使用以致JavaScript引擎决定积极地优化它,则V8(至少)使用的一个这样的优化是识别对象的生命周期是否完全包含在函数中调用,如果是的话,将它分配到堆栈上,因为堆栈分配和清理速度非常快。因此,一个对象完全可能在堆栈而不是堆中(并且,如果我没记错的话,可以在必要时将它从堆栈复制到堆中,因为在某些代码路径中它可以存活到超出堆栈的末尾。功能调用)。