这些问题总是取决于引擎。在 V8(谷歌浏览器、Node.js)中:
对象和数组并没有根本不同。为了实现简单,所有对象都有一个外部元素数组,其中存储了正整数的属性。
因此,当您这样做时,是 Javascript Array 对象还是任何 javascript 对象obj[5]
都没有关系- 它会访问对象的外部元素数组。obj
因此,如果您创建了这样的对象:
var a = {
a: 3,
b: 4,
c: {},
5: 5,
6: 6
};
对象布局将是:
[HiddenClassPointer, PropertiesArrayPointer, ElementsArrayPointer, TaggedSmallInteger(3), TaggedSmallInteger(4), JSObjectPointer]
请注意命名字段如何与内部字段并排存储。如果您现在在事后添加任何属性,它将进入第二个字段指向的外部属性数组,而不是直接存储在对象上。
带有整数键的“字段”将位于指向的外部元素数组中,ElementsArrayPointer
如下所示:
[HiddenClassPointer, TaggedSmallInteger(25), TheHolePointer, TheHolePointer, TheHolePointer, TheHolePointer, TheHolePointer, TaggedSmallInteger(5), TaggedSmallInteger(6), ...more hole pointers until 25 elements]
25 是后备数组的长度。我很快就会回来。
需要孔指针来消除用户给出的显式未定义值和数组中的实际孔之间的歧义。当您尝试检索 a[3] 时,它会返回您,undefined
因为有一个洞。所以实际的孔对象不会返回给用户。所以实际上有 3 种不同类型的 null :P
初始长度 25 来自公式(initial index + 1 ) + ((initial_index + 1 ) / 2) + 16
so 6 + 7/2 + 16 = 25
。您可以在堆快照中看到它。
( 108 - 8 ) / 4 === 25