Past that, even if you start defining non-integer names you still store the integer-named properties in a contiguous chunk of memory and store the named properties separately. This is why in V8 and SpiderMonkey the property order for an object (as seen by a for-in loop, say) doesn't match property addition order. Instead, the integer-named properties are enumerated first (in SpiderMonkey up to a certain limit) and then the other properties in addition order. So yes, the requirements are similar and JS engines throw some of them (property order preservation) under the bus to improve performance.
In SpiderMonkey, even once you have lots of properties (and are sparse and whatnot) and have converted to a hashtable, things are not that simple. The values are still stored in a contiguous memory buffer. There is a linked list of property descriptors which contain things like the property name and an index into the buffer, as well as metadata like whether the property is readonly and whatnot. This list is shared across objects that have the same property names added to them in the same order (though possibly with different values). What's stored in the hashtable, which can also be shared across objects is a mapping from property name to nodes in this linked list.
In practice, objects that have a dedicated hashtable just for that one object instead of sharing property descriptors with multiple other objects end up being pretty rare.
Lastly, JS engines are at least experimenting with unboxed storage for arrays. That is, instead of having a memory region filled with JS values, which might be of any type, detect at runtime that your array happens to only contain integers and have a memory region filled with integers; storing a non-integer will then cause a realloc and boxing of the data.