If declarations in conditionals were possible ( @span tc39 proposal being discussed right now!) what would you expect this to log?
let foo = 1;
if (let foo = 0) { console.log(foo) }
else { console.log(foo) }
Discussion
If declarations in conditionals were possible ( @span tc39 proposal being discussed right now!) what would you expect this to log?
let foo = 1;
if (let foo = 0) { console.log(foo) }
else { console.log(foo) }
@leaverou Seeing that the evaluation of the condition in `if ()` applies to both the statement's then and else branches and that the declaration is evaluated first (e.g. here, the `if ()` condition evaluates as false), the `foo` value _has_ to be `0` in the else branch as well imo. If one wants the (re-)declaration of foo to only apply in the then branch, one should declare it in the then branch, not in the `if ()` condition or outside the statement.
@leaverou out of all the things I've wanted a programming language to be able to do in 25 years this has never been one, cannot imagine why you would want it.
@leaverou of be pushing back on this one in code review. Valid or not.
No declarations in my conditions thanks.
@leaverou I would copy Go here, and encourage folks to use the "if (let x=0; x!=0)" form. As @AmeliaBR says, the scope has to cover the else. My preference would be to say that even though there's a nested scope, you get a redeclaration error for this kind of shadowing, but both Rust and Go allow it (Rust shadows even more aggressively but doesn't have this kind of declaration), so JavaScript probably should too.
@jyasskin @AmeliaBR “The scope has to cover the else” is not clear to me at all. No existing precedent with in the language (for and friends only have a single block). Prior art in other langs strongly leans towards no else binding.
In the end it looks like it will be an error, exactly because mental models are different.
@leaverou @jyasskin I guess one way to look at is as "syntactic sugar" and to deconstruct it:
This makes sense, with one scope around both if and else:
```js
{
let x=0;
if (x) {a()}
else {b()}
}
```
This would be a syntax error, with a scope around the declaration & if statement, but the else on the outside:
```js
{
let x=0;
if (x) {a()}
}
else {b()}
```
@leaverou I parse that as “let foo = 0 has successfully ran, the return value would be true for success”, so ‘1’ is the sensible log
@leaverou I voted 0, although I'm not sure, and the reason I'm not sure is that this sort of C-ish thing confuses me to absolute misery and up until now I have been very glad that JS doesn't have it. As a data point :)
@leaverou I'd expect there to be implicit scoping brackets around the whole if/else construct, and same as with for loops & such. The else block relies on the conditional in the if statement, so it should inherit the scope of any let statements from that conditional.
(But I read the code too fast, didn't see the `else`, and voted incorrectly. 🤦🏻♀️)
My brain can readily justify either "0" or"Nothing, it throws", but not the others.
If it's not a new scope, then it violates the "can't redeclare the same variable in the same scope" rule¹ and thus the "Nothing, it throws"
If it's a new scope, under the "if" feels like it should be within that sub-scope, shadowing the outer-scoped foo=1, and produce the "0".
⸻
¹ at least according to MDN
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let#redeclarations
If using two "let"s in a row was an error, such as
let foo = 1;
let foo = 2;
then I'd expect the "Nothing, it throws". But at least in the FF JS console, it happily accepts the `let foo = 2;` which would at least seem scoped to the children of the "if", so I go with "0" for the answer.
Of similar interest, if you print foo after the entire "if" block
let foo = 1;
if (let foo = 0) { console.log(foo) }
else { console.log(foo) }
console.log(foo) // this one
should the second output be 0 or 1? (does the "if" create a new scope, or does it use the containing scope)
@leaverou I voted throw, but I think it should actually behave the same way as in for. So let/const declared inside the if would be scoped to the if block. What I’m not sure of though is if the scope would include inside else or not since it’s a different block. Or inside an else if? Can the same variable be defined again?
How would it behave in a situation like:
let foo = 1;
if (let foo = 0) { console.log(foo) }
else if (let foo = 1) { console.log(foo) }
else { console.log(foo) }
GitHub poll: https://github.com/LeaVerou/blog/discussions/139
You need to log in to see that page.