I really like the way scheme does it. In order to mutate a variable (which is actually comparatively rare), you have to use `set!`, and to create a binding (much more common), you just call `define`. `set!` is incapable of creating new bindings, and will error if the variable is in scope, while `define` will always shadow.
The js and coffeescript ways of handling this seem both to come down to the assignment operator being used for both creating bindings and mutating them, which gets confusing, and causes the failure modes you described.