Brendan Eich (2013-12-25T18:44:21.000Z)
domenic at domenicdenicola.com (2014-01-06T14:09:24.566Z)
raul mihaila wrote: > What I want is both similar to A2 and B2, but it's different in that > there is only 1 scope for the inner variable. There is only one inner scope for the braced block in Waldemar's example, in any of {A,B}{1,2}: ```js let x = "outer"; function g() {return "outer"} { g(); function f() { ... x ... g ... g() ... } f(); var t = some_runtime_type; const x:t = "inner"; function g() { ... x ... } g(); f(); } ``` Note that function-in-block declarations hoist to top of block -- I should have cited that too, for emphasis, in my last message's closing. > The inner variable is just a local variable, but it's initialized in > the hoisting process with the value from the outer scope. That's unusual -- why would it take on the out same-named variable's value? Note it won't work for 'const', only 'let'. Is there any difference for 'let' between your proposal and A2, lexical window? Let's see, by simplifying the example to make the inner 'const x' into a 'let x': ```js let x = "outer"; function g() {return "outer"} { g(); function f() { ... x ... g ... g() ... } f(); let x = "inner"; function g() { ... x ... } g(); f(); } ``` Your proposal sounds equivalent to this: ```js { let x = outer`x`; // quasi syntax for outer x g(); function f() { ... x ... g ... g() ... } f(); x = "inner"; function g() { ... x ... } g(); f(); } ``` Notice the call g() in f's body, and the call f() before x = "inner". This means that f captures (closes over) the block-local x, but its value depens on when f is called. The call of f(); right before end of block sees x = "inner". The call from just before x = "inner"; sees "outer", as does the reference to x in g of course (that capture is not in question). > Initially I was thinking only about var scoped variables but I think > this should work for the let scoped variables as well. We would need a > new keyword then. Adds some complexity but at least there's only one > scope. There is only one block scope in any event. I am not sure what you mean here. In any case, we aren't adding another keyword, and your approach does not work for 'const' at all. For 'let' or any new keyword, it hoists and implicitly initializes, which is too implicit and magical, even for JS. > I didn't study the details about let scope variables in the current > spec but I understand that this should throw: > > ```js > { > (function () { > x; // throws - B1 case > })(); > x; // x = undefined, right? - not A1 case because it doesn't throw > let x = 10; > }; > ``` First, you don't show any outer x at all, so this involves no inner/outer shadowing/windowing/dead-zoning. Second, the x; before let x = 10; would throw per current spec. I don't know what you mean by "not A1" in the comment, since the current spec doesn't implement A1 (lexical dead zone), it implements B1 (temporal dead zone). > Currently in FF there's no error here, x is undefined. Please don't go by implementations yet. They are in various states with respect to the ES6 draft spec. Firefox's 'let' dates back to ES4 proposals. It will be updated. > In Chrome there's an error about some extended mode which, from what I > understand, doesn't exist anymore. There should be a temporal dead zone error, if you enable the flag for harmony_let. > Currently I achieve what I want by defining a local variable whose > name is prefixed with 'local' and assigning it the value I need. It's > bad if I want to do the same in multiple execution levels. My proposal > is far more readable because it looks less weird. It's far less readable, though, because of the implicit magic initialization from outer shadowed x. What if there is no outer x? And 'const' does not work at all. We can't have two values for a given 'const' binding.