I always thought of it as being constant values for primitives (stack) and references/pointers to objects (heap). A really annoying distinction, wish we had proper immutable records.
My take: in early versions of JS garbage collection implementation was much worse. Mutating an existing object was therefore a less expensive operation compared to replacing the object with a new object and orphaning the old object for the garbage collector to handle
In JS/TS anonymous functions with nested scope are everywhere. const binding a variable helps you see accidental shadowing assignment. These bugs can be very expensive. Each one you don't experience (because you use const) is worth the time typing the extra letter for the entirety of the project.
I do think this helps catch bugs (vs let) when people are working in larger scopes and use common names, especially without something like TS. And it helps be explicit about primitives, but due to JS messiness, it absolutely creates confusion with objects.
It just means that you don't have to check whether the variable is assigned something else at a later point. This might be helpful for very long pieces of code, but I don't think this is a common problem.
Java's `final` seems to be a better name for the exact same concept.
π The variable is just a name. The thing they refer to is the value. You set the value they refer to via "assignment". You can assign a new value (change what value the variable refers to) if it was defined with `var` or `let`.
Comments
Or const was an afterthought π
const a = "hello"
a = "world" // error - can't reassign
const b = ["hello"]
b.push("world") // okay! No reassignment!
const i = 1
i++ // error!
When we try to increment `i`, JS actually tries to assign a value of `2` to `i` to replace `1`, causing an error!
Java's `final` seems to be a better name for the exact same concept.
That being said, this is no more complicated than the rules of the English language.