Empty slots are skipped in map() and for-in, but not in for-of and the new array from map() will have the same empty slots. delete will change a slot to empty, it won't change the length of the array.
PHP basically has arrays and maps merged into one. Basically like Lua does.
It is pretty handy. Not sure what you find insane about it.
Of course the functions for arrays in the standard library are consistently inconsistent but that is just a general PHP thing. Isn't a big deal when you use an IDE.
How about array_filter() returning an associative array, because it doesn't renumber the indexes? You need to run it through array_values() after. You run into this all the time when converting to json.
For something more obscure but equally infuriating, how about using iterator_to_array() on anything that uses `yield from`? Everything yielded that way will overwrite previously yielded values, unless you pass a magic boolean parameter that of course defaults to doing the wrong thing (PHP is chock full of those). OFC it's because of the behavior of array keys.
How about when you do want associative array semantics and use a string index that consists entirely of numeric digits? It gets cast into an int, always, and you cannot control that. This is super "fun" when you run array_keys on your associative array you only used string keys on, and naïvely think it will return only strings. Crash at runtime if your function was declared to just take a string.
There are so many more WTFs, these were just off the top of my head from issues I've encountered recently. I make my living with PHP, but you'll never see me defending arrays. Though at least they're zero-based As The Deity Intended It.
Still, much saner than PHP arrays.