I makes chaining things while debugging so much harder:
let a = a.project();
let a = debug(a);
let a = a.eject();
vs let a1 = a.project();
let a1d = debug(a1);
let a2 = a1d.eject();I makes chaining things while debugging so much harder:
let a = a.project();
let a = debug(a);
let a = a.eject();
vs let a1 = a.project();
let a1d = debug(a1);
let a2 = a1d.eject();Given that JS doesn't restrict the type of a declaration you can just assign a new value to it, place it in a small scope or use a chain.
I don't know - it's never confusing to me. I just use the IDE that allows me to view the types of the variables whenever I need to see them.
IDE also highlights the definitions and then the usages of the variable, including the syntax scope where it's used.
You're definitely using the wrong tools for the job if you get confused with that little detail.
>> Given that JS doesn't restrict the type of a declaration you can just assign a new value to it, place it in a small scope or use a chain.
Yeah, but I don't want to semantically assign a new value to the variable. I want this to be a new variable, because it is a new variable.
So the point of var is slightly over exaggerated because they could have gone the python way and simply allow declarations to be anything that is an assignment.
So var and let are only tangential to the whole declaration process and only indicate the scope in which the variable is bound.
I feel confused. Why do you want your assignment statements to be prefixed with var's and let's?
let a = a.project();
a = debug(a)
a = a.eject();
This is perfectly legal.Limiting a variable's scope can help avoid subtle and potentially annoying errors. For example, if you use a let variable inside an if block, it'll only be accessible by code inside the block. If you use var inside an if block, your variable will be visible to the entire function.
In the scenario with var/let I need to grok the code in order to tell which variables are visible in my current scope.
if(something) var foo = 1;It also throws and error if it's used before it's declared.
Let basically fix some minor issues that hard-bitten JavaScript developers have learned to avoid.
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).
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).
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).
When you're refactoring, you then have to be much more careful when moving lines of code of code around. With unique names, you get more of a safety net (including compile time errors if you're using something like TypeScript).
If you want a variable you can assign successive different values to, it's an entirely different thing, and there have always been var and the assignment operator for that.
That's pure BS. This is only true for atomics, the value can change (under let, var and const) as we can easily see with Array.push, for example.
var a = ...;
a = a.project();
a = debug(a);
a = a.eject();Rust allows this, and it really clears codes up. I don’t have to make up different identifiers for same data but different representations. (e.g. I would do the above code in JS as... someKindOfDataAsArray = [...someKindOfObectAsNodeList])
let projected = a.project();
let debugged = debug(projected);
let ejected= debugged.eject();And by the way - if you paid attention in the first place my post actually has exactly what you've just written.