Brendan Eich <mailto:[email protected]>
January 24, 2012 11:24 AM
Andreas Rossberg <mailto:[email protected]>
January 24, 2012 10:32 AM
Taken literally, an implicit block scope at toplevel would imply that
let/const-bound properties won't show up on the global object at all.
That seems to devalue the global object and/or let.
I prefer to think of it as saving 'let' from the degradations of the
global object ;-).
I am skeptical we will banish var, ever. Consider the object detection
pattern:
if (!this.foo) {
var foo = function () {
...
};
}
No way to make this work with let.
(Part of) what I proposed in the OP of this thread is that for the
toplevel, we can still safely reflect let/const bindings on the global
object, but through accessor properties -- just like with module
instance objects. Solves all the problems we just discussed, while
also keeping let useful as the new var.
I saw, clever approach -- haven't had time to evaluate it for
compatibility. Seems optimizable.
/be
Andreas Rossberg <mailto:[email protected]>
January 24, 2012 10:32 AM
Taken literally, an implicit block scope at toplevel would imply that
let/const-bound properties won't show up on the global object at all.
That seems to devalue the global object and/or let.
(Part of) what I proposed in the OP of this thread is that for the
toplevel, we can still safely reflect let/const bindings on the global
object, but through accessor properties -- just like with module
instance objects. Solves all the problems we just discussed, while
also keeping let useful as the new var.
Var would keep its current semantics, aliasing a data property. For
functions, it doesn't matter much either way, but for consistency with
other static bindings I'd move to accessor-based semantics in ES6.
/Andreas
Brendan Eich <mailto:[email protected]>
January 24, 2012 9:49 AM
Andreas Rossberg <mailto:[email protected]>
January 24, 2012 2:37 AM
On 23 January 2012 19:25, Brendan Eich<[email protected]> wrote:
Andreas Rossberg<mailto:[email protected]>:
V8 currently allows
var w = 1; w = 2; print(w); const w = 3
which will output 2. The idea most likely was that const should behave
like var. This, and other, similar examples clearly have to break if
should const become official in classic mode, so the compatibility
argument may not carry far.
SpiderMonkey:
js> var w = 1; w = 2; print(w); const w = 3
typein:19: TypeError: redeclaration of var w:
typein:19: var w = 1; w = 2; print(w); const w = 3
typein:19: ....................................^
js> var w = 1
js> const w = 3
typein:22: TypeError: redeclaration of var w
However:
js> const w = 3; var w = 1; print(w);
3
This follows from var not disturbing a pre-existing binding. Or so we
thought long ago when adding const, but that was years before const as
initialize-only-and-at-most-once let.
Why does V8 do something else, do you know the impetus for diverging?
No, unfortunately I don't know the full history there. I can try to
find it out.
But just to be obnoxious, with Firefox:
print(c);
Object.defineProperty(this, 'c', {value: 1});
print(c);
const c = 2;
print(c);
=> undefined 1 2
You bet -- const does redefine the global property, unlike var. This
is not something we propose for standardization, of course!
Or even:
print(c);
Object.defineProperty(this, 'c', {value: 1, writable: true});
print(c);
c = 2;
print(c);
const c = 3;
print(c);
=> undefined 1 2 3
Apparently, FF avoids breaking the object model only for the price of
keeping the non-writable const property configurable until the actual
initialization -- effectively breaking const completely.
More fun:
js> function f(k) {
for (var i = 0; i < k; i++) {
const j = i*i;
a.push(j);
}
}
js> a = []
[]
js> f(10)
js> a
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
SpiderMonkey const has never been initialize-at-most-once. Some people
claim to like this, but we are going to try breaking it in favor of ES6.
Consequently, I maintain my claim that it is impossible to reconcile
sane let/const semantics with the idea of having toplevel bindings
represented as data properties on the global object.
I agree. For ES4 we equated let to var at top-level, a mistake. For
ES6 IIRC you have proposed an implicit block scope at top level (of
functions at least, I don't see why not programs as well), whereby let
and const bind lexically. Only var and function make global object
properties.
If there is some
trick for "hiding" accessor semantics that doesn't break the object
model then I'd be really interested in seeing it. :)
Me too.
/be
Andreas Rossberg <mailto:[email protected]>
January 24, 2012 2:37 AM
On 23 January 2012 19:25, Brendan Eich<[email protected]> wrote:
Andreas Rossberg<mailto:[email protected]>:
V8 currently allows
var w = 1; w = 2; print(w); const w = 3
which will output 2. The idea most likely was that const should behave
like var. This, and other, similar examples clearly have to break if
should const become official in classic mode, so the compatibility
argument may not carry far.
SpiderMonkey:
js> var w = 1; w = 2; print(w); const w = 3
typein:19: TypeError: redeclaration of var w:
typein:19: var w = 1; w = 2; print(w); const w = 3
typein:19: ....................................^
js> var w = 1
js> const w = 3
typein:22: TypeError: redeclaration of var w
However:
js> const w = 3; var w = 1; print(w);
3
Why does V8 do something else, do you know the impetus for diverging?
No, unfortunately I don't know the full history there. I can try to find it out.
But just to be obnoxious, with Firefox:
print(c);
Object.defineProperty(this, 'c', {value: 1});
print(c);
const c = 2;
print(c);
=> undefined 1 2
Or even:
print(c);
Object.defineProperty(this, 'c', {value: 1, writable: true});
print(c);
c = 2;
print(c);
const c = 3;
print(c);
=> undefined 1 2 3
Apparently, FF avoids breaking the object model only for the price of
keeping the non-writable const property configurable until the actual
initialization -- effectively breaking const completely.
If the property wasn't configurable, then the initialization would
need to modify a non-writable, non-configurable data property, which
is a clear violation of the JS object model. It is what V8 does,
though. So in V8, the above examples are rejected, but instead,
objects break.
Consequently, I maintain my claim that it is impossible to reconcile
sane let/const semantics with the idea of having toplevel bindings
represented as data properties on the global object. If there is some
trick for "hiding" accessor semantics that doesn't break the object
model then I'd be really interested in seeing it. :)
/Andreas