5 ms·
Without getting into the merits of allowing redefines in a loosely typed language, the simple reason why JS can't support this is hoisting. Any var/let stateme
by addicted 7y ago
Without getting into the merits of allowing redefines in a loosely typed language, the simple reason why JS can't support this is hoisting.
Any var/let statement of the form var a = 1; is interpreted as 2 statements. (1) The declaration of the variable which is hoisted to the beginning of the variable scope, and the (2) setting of the value, which is done at the location the var statement is at.
Having multiple let statements would mean the same variable is declared and hoisted to the same location multiple times. So it's basically unnecessary and breaks hoisting semantics.
In addition, the downside risk of accidentally redefining a variable is probably far greater than the semantic benefits of making the redefinition clear to a reader (esp since I think that benefit is extremely limited in a loosely typed language like JS anyways).
- jacobwilliamroy 7y agoThis human gets it. I'd like to add that if you would like to be clear about what your assignment is doing, put some comments in there.
- hajile 7y agoThat's not quite accurate. It's actually the reverse. Think of the closure as an object. It contains variables like `this`, `arguments`, a pointer to the parent closure, all your variables, etc. The interpreter needs to create this closure object BEFORE it runs the function. Before the function can run, it has to be parsed. It looks for any parameters, `var` statements, and function statements. These are all added to the list of properties in the object with a value of `undefined`. If you have `var foo` twice, it only creates one property with that name. Now when it runs, it just ignores any `var` statements and instead, it looks up the value in the object. If it's not there, then it looks in the parent closure and throws an error if it reaches the top closure and doesn't find a property with that name. Since all the variables were assigned `undefined` beforehand, a lookup always returns the correct value. `let` wrecks this simple strategy. When you're creating the closure, you have to specify if a variable belongs in the `var` group or in the `let` group. If it is in the `let` group, it isn't given a default value of `undefined`. Because of the TDZ (temporal dead zone), it is instead give a pseudo "really undefined" placeholder value. When your function runs and comes across a variable in the let group, it must do a couple checks. Case 1: we have a `let` statement. Re-assign all the given variables to their assigned value or to `undefined` if no value is given. Case 2: we have an assignment statement. Check if we are "really undefined" or if we have an actual value. If "really undefined", then we must throw an error that we used before assignment. Otherwise, assign the variable the given value; Case 3: We are accessing a variable. Check if we are "really undefined" and throw if we are. Otherwise, return the value. To my knowledge, there's no technical reason for implementing the rule of only one declaration aside from forcing some idea of purity. The biggest general downside of `let` IMO is that you must do extra checks and branches every time you access a variable else have the JIT generate another code path (both of which are less efficient).
- addicted 7y agoWe are on the same page. My point is having 2 let or var statements doesn't actually do anything on the interpreter side. If JS allowed 2 var/lets without complaining, it would be entirely a social convention as to what that meant, since it would have no effect on the actual code that was run. And the social convention benefit (which could more easily be achieved with just putting a comment at the end) is probably far outweighed by the many, real examples I've seen where someone has accidentally created a new variable without realizing that variable already exists in scope. Disallowing multiple vars helps linters identify these situations (which are far more common with var's function level scoping than let's block level scoping).