JSArray
是继承自 JSObject
的,所以在 JavaScript 中,数组可以是一个特殊的对象,内部也是以 key-value 形式存储数据,所以 JavaScript 中的数组可以存放不同类型的值。JSArray
继承于 JSObject
,从注释上看,它有两种存储方式:FixedArray
,并且数组长度 <= elements.length()
,push
或 pop
时可能会伴随着动态扩容或减容HashTable
(哈希表),并且数组下标作为 key
fast
模式下数组在源码里面叫 FastElements
,而 slow
模式下的叫做 SlowElements
。FixedArray
是 V8 实现的一个类似于数组的类,它表示一段连续的内存,可以使用索引直接定位。新创建的空数组默认就是快数组。当数组满(数组的长度达到数组在内存中申请的内存容量最大值)的时候,继续 push
时, JSArray
会进行动态的扩容,以存储更多的元素。arr
增加一个 2000
的索引时,arr
被转成慢数组。节省了大量的内存空间(从索引为 2 到索引为 2000)。4
:push
操作时,一旦发现数组内存不足,将进行扩容。push
的操作是用汇编实现的,在 c++ 里嵌入的汇编,以提高执行效率,并且在汇编的基础上用 c++ 封装了一层,在编译执行的时候,会将这些 c++ 代码转成汇编代码。new_capacity = old_capacity /2 + old_capacity + 16
push
第 5 个的时候,容量将会变成:new_capacity = 4 / 2 + 4 + 16 = 22
push
操作时,发现数组内存不足pop
操作时,会判断 pop
后数组的容量,是否需要进行减容。push
使用汇编实现的, pop
使用 c++ 实现的。pop
后,如果数组容量大于等于 length 的 2 倍,则进行容量调整,使用 RightTrimFixedArray
函数,计算出需要释放的空间大小,做好标记,等待 GC 回收;如果数组容量小于 length 的 2 倍,则用 holes 对象填充。pop
操作时,获取数组 length
length - 1
上的元素(要删除的元素)length - 1
RightTrimFixedArray
函数,计算出需要释放的空间大小,并做好标记,等待 GC
回收holes
对象填充JSArray
继承自 JSObject
,或者说它就是一个特殊的对象,内部是以 key-value 形式存储数据,所以 JavaScript 中的数组可以存放不同类型的值。它有两种存储方式,快数组与慢数组,初始化空数组时,使用快数组,快数组使用连续的内存空间,当数组长度达到最大时,JSArray
会进行动态的扩容,以存储更多的元素,相对慢数组,性能要好得多。当数组中 hole
太多时,会转变成慢数组,即以哈希表的方式( key-value 的形式)存储数据,以节省内存空间。