In V8, if your array only contains integers, it’ll be backed by a C++ array of integers. Typically, the backing array will be bigger than the number of integers it currently contains. If it contains a mixture of integers and floating point values or only floating point values, it’ll be backed by an array of doubles.
If you call
push() when the backing array is full, it’ll allocate a new, bigger backing array, copy the existing elements over, and then add the new value you pushed. This is similar to the implementation of
ArrayList in Java or
vector in C++.
All of the above is only sure to apply if your array is packed, and not sparse – i.e., you don’t have any gaps in the array. If you do something like...
let abc = [1,2,3];
abc = 50;
...you now have a sparse array. If it is not too spare, it’ll still be backed by an array, with empty array indices replaced with a ‘hole’ value. If you look at V8’s C++ array source (linked below), you’ll see calls to
element->is_the_hole(i). If an array is very sparse, it’ll no longer be backed by an array in memory. Instead, it will be backed by a dictionary/hashtable, and it’ll take longer to both access elements and iterate through the array.
If you’re interested, you can read through V8’s array implementation in C++ here. You’ll notice that it often checks the following constants:
PACKED_SMI_ELEMENTS – a packed integer array
PACKED_DOUBLE_ELEMENTS – a packed double array
PACKED_ELEMENTS – a packed object array
HOLEY_SMI_ELEMENTS – a sparse integer array
HOLEY_DOUBLE_ELEMENTS – a sparse double array
HOLEY_ELEMENTS – a sparse object array
DICTIONARY_ELEMENTS – a very sparse array that is backed by a dictionary
And you’ll see that it always tries to do whatever will be fastest for the array it is operating on. Lots of builtin functions like
concat do different things depending on the array’s density and what kind of elements it contains.
Some other things to keep in mind: if you have an array that only contains integers, and you push a floating point number or other type into it, it will be ‘downgraded’ for the rest of its life, even if you purge the non integers from it.
Actually, if you grab an early copy of the Mozilla source code from 20 years ago, you’ll find that arrays were backed by ordinary JS objects without much optimization, just some extra code to handle special cases like the `
If you’re interested in diving even deeper into V8’s internals, I suggest starting by reading through the source files I linked to above. If you’re not used to C++, understanding it will be a bit of a chore at first.
I spent 5 years working for Ottawa startups before returning home to Toronto. During Covid I decided to escape the big city and moved north to Penetanguishene, Ontario.