Big O of JavaScript arrays

Big O of JavaScript arrays

Arrays in JavaScript are very easy to modify by adding and removing items. It somewhat masks the fact that most languages array’s are fixed-size, and require complex operations to resize. It seems that JavaScript makes it easy to write poorly performing array code. This leads to the question:
What performance (in terms of big O time complexity) can I expect from JavaScript implementations in regards to array performance?
I assume that all reasonable JavaScript implementations have at least the following big O’s.

Access – O(1)
Appending – O(n)
Prepending – O(n)
Insertion – O(n)
Deletion – O(n)
Swapping – O(1)

JavaScript lets you pre-fill an array to a certain size, using new Array(length) syntax. (Bonus question: Is creating an array in this manner O(1) or O(n)) This is more like a conventional array, and if used as a pre-sized array, can allow O(1) appending. If circular buffer logic is added, you can achieve O(1) prepending. If a dynamically expanding array is used, O(log n) will be the average case for both of those.
Can I expect better performance for some things than my assumptions here? I don’t expect anything is outlined in any specifications, but in practice it could be that all major implementations use optimized arrays behind the scenes. Are there dynamically expanding arrays or some other performance boosting algorithms at work?
The reason I’m wondering this is because I’m researching some sorting algorithms, most of which seem to assume appending and deleting are O(1) operations when describing their overall big O.


Solution 1:

In contrast to most languages, which implement arrays with, well, arrays, in Javascript Arrays are objects, and values are stored in a hashtable, just like regular object values. As such:

  • Access – O(1)
  • Appending – Amortized O(1) (sometimes resizing the hashtable is required; usually only insertion is required)
  • Prepending – O(n) via unshift, since it requires reassigning all the indexes
  • Insertion – Amortized O(1) if the value does not exist. O(n) if you want to shift existing values (Eg, using splice).
  • Deletion – Amortized O(1) to remove a value, O(n) if you want to reassign indices via splice.
  • Swapping – O(1)

In general, setting or unsetting any key in a dict is amortized O(1), and the same goes for arrays, regardless of what the index is. Any operation that requires renumbering existing values is O(n) simply because you have to update all the affected values.