There is no exception for ANY data structure that includes references to other data structures or primitives. Not only can you add or remove elements from an array, you can change them in place.

A const variable that refers to an array is a const variable. The array is still mutable. That's not an exception, its also how a plain-old JavaScript object works: You can add and remove properties at will. You can change its prototype to point to something else and completely change its inheritance chain. And it could be a const variable to an unfrozen POJO all along.

That is not an exception to how things work, its how every reference works.

I know, and I do agree it's consistent, but then it doesn't make any sense to me as a keyword in a language where non-primitives are always by-reference.

You can't mutate the reference, but you _can_ copy the values from one array into the data under an immutable reference, so const doesn't prevent basically any of the things you'd want to prevent.

The distinction makes way more sense to me in languages that let you pass by value. Passing a const array says don't change the data, passing a const reference says change the data but keep the reference the same.

The beauty of `const` in JS is that it's almost completely irrelevant. Not only does it have nothing to do with immutability, it's also local. Which means, if I were to write `let` instead of `const`, I could still see whether my code reassigned that variable at a glance. The keyword provides very little in the way of a guarantee I could not otherwise observe for myself.

Immutability is completely different. Determining whether a data structure is mutated without an actual immutable type to enforce is impractical, error-prone, and in any event impossible to prove for the general case.