If you're interested in how the v8 implementation works, check out the source code. When using unshift
, the array will adjust itself to accommodate the arbitrary number of arguments passed.
UnshiftImpl
eventually calls AddArguments
with a start_position
of AT_START
, which leads to this else
statement:
// If the backing store has enough capacity and we add elements to the
// start we have to shift the existing objects.
Isolate* isolate = receiver->GetIsolate();
Subclass::MoveElements(isolate, receiver, backing_store, add_size, 0,
length, 0, 0);
This then takes us to the MoveElements
function.
static void MoveElements(Isolate* isolate, Handle<JSArray> receiver,
Handle<FixedArrayBase> backing_store, int dst_index,
int src_index, int len, int hole_start,
int hole_end) {
Heap* heap = isolate->heap();
Handle<BackingStore> dst_elms = Handle<BackingStore>::cast(backing_store);
if (len > JSArray::kMaxCopyElements && dst_index == 0 &&
heap->CanMoveObjectStart(*dst_elms)) {
// Update all the copies of this backing_store handle.
*dst_elms.location() =
BackingStore::cast(heap->LeftTrimFixedArray(*dst_elms, src_index))
->ptr();
receiver->set_elements(*dst_elms);
// Adjust the hole offset as the array has been shrunk.
hole_end -= src_index;
DCHECK_LE(hole_start, backing_store->length());
DCHECK_LE(hole_end, backing_store->length());
} else if (len != 0) {
WriteBarrierMode mode = GetWriteBarrierMode(KindTraits::Kind);
dst_elms->MoveElements(heap, dst_index, src_index, len, mode);
}
if (hole_start != hole_end) {
dst_elms->FillWithHoles(hole_start, hole_end);
}
}
It's worth noting that v8 categorizes different element kinds
based on the content of the array, impacting performance.
Predicting the exact performance can be tricky as it depends on various factors like the types of elements passed and the presence of holes in the array. Generally speaking, since unshift
requires allocating more space in the array, it likely operates at O(N) complexity (scaling linearly with the number of elements). Feel free to correct me if I'm mistaken!