ArrayDeque, LinkedHashMap, TreeMap, PriorityQueue, even LinkedList. Their interfaces have gotten pretty built-out, too, with methods like computeIfAbsent.
It also has a rich collection of concurrent data structures, but those aren't useful in Javascript (yet).
Lucky for you, JS already has good solutions for most of those things.
LinkedList is almost indistinguishable from an growable array. Since the JS array grows by default, you're covered for the kinds of things you'd want a linked list for (in fact, most older JS implementations actually implemented arrays as linked lists).
ArrayDeque's big claim to fame is add/remove from both ends. That's also covered by the standard array (shift/unshift, pop/push).
Linked hashmap's big feature is maintaining insertion order. The JS Map type does this automatically. JS Objects don't do this officially, but since so much legacy code depends on this "feature", it is implemented for objects across all major browsers.
Priority Queue isn't in JS, but I'd argue it's rather niche and rather few async frontend JS projects need it. On the backend, one extra import is hardly a big deal.
There is also no treemap. They are simple to implement (esp with proxies). JS objects store all keys as strings and `Object.keys(foo).sort()` is probably about as fast. As an additional issue, JS maps can have keys of different types, so deciding how to perform that sort would be very difficult. This also seems like a niche issue that belongs outside the standard library.
> LinkedList is almost indistinguishable from an growable array. Since the JS array grows by default, you're covered for the kinds of things you'd want a linked list for (in fact, most older JS implementations actually implemented arrays as linked lists).
Not only they have different performance for various operations (append, prepend, indexing, removal in the middle), but perhaps even more importantly, linked lists can share data if it's immutable. So an array is not a replacement.
You'd be correct -- if we were talking about a lower-level language.
JS implementations are free to choose whichever array representation works best be that hashtable, struct, class, linked list, array, or whatever. Modern JITs use a couple different approaches that have been found to be fastest and can even switch representations on the fly based on several factors (is the array homogeneous, is it sparse, is it short, med, or long, and so on).
Even moving away from JS, there should be a healthy skepticism for basic O notation about data structures and algorithms. When your processor is thousands or millions of times faster than your ability to send over data from memory, the notion of what is faster changes a lot. If my linked list misses in cache because it's memory isn't sequential, then the time it takes to add an element and read may be much longer than copying an array and expanding it a few entries (especially if a fill pointer is used).
Are you saying that JS implementations somehow know whether the array is used to store immutable values, and will switch implementations to allow for sharing?
In JS, primitives are immutable -- number, functions (but not the fn object), regex, strings, and booleans. All other types are not immutable -- Object, Array (actually an Object), Map, Set, TypedArray, etc. Even if a linked list were added, it would not be immutable.
That said, JS has Object.freeze() which can make an object immutable. You could do this recursively to make a guaranteed immutable object. Immutable libraries in JS tend to use other methods for performance reasons though IIRC.
It also has a rich collection of concurrent data structures, but those aren't useful in Javascript (yet).