Kevin Smith wrote:
function f(x) {
console.log(x);
if (truthy()) {
with ({x: 'ha ha'}) {
var x = 'ho ho';
console.log(x);
}
}
function x(){}
console.log(x);
}
In these cases there is information flowing right to left, even
across unbalanced left brace!
You're not seriously arguing for how new things should work based on
"with" and "arguments" are you? : )
No arguments object usage here, and takea way the 'with' and you still
have hoisting to contend with, even across a (non-body) left brace if
the var is nested.
My point is serious, in that we are not bound to follow C, C++, or Java
and try to separate formal parameter scope, default parameter
initialization, or other observables from those languages, just because
of that left curly brace at the start of a function body.
This is JS. We can't change it. Are default parameters really the
place to make a new last stand for something different?
Maybe not. It may not be worthwhile to try and maintain the "curly
law" here, but just as a thought experiment:
function g() { return "outer"; }
function f(a = g()) { return a; function g() { return "inner"; } }
Function hoisting is what it is, so putting nested function g's
declaration after the return statement shouldn't be relevant to us in
this discussion. You could as well have put it before the return. Just
sayin' ;-).
console.log(f());
What should we see logged? If we're inclined to think that curlies
should define scope boundaries, then we might answer "outer". In
order to make that happen, we'd need to introduce a new scope in
between f's declaration and f's body:
{0: g, f {1: a } {2: a, g } }
where 0 is the outer scope, 1 is the scope of parameter default
expressions, and 2 is the function body scope. This model isn't
conceptually clean either though, because we have weird "copy-like"
semantics as parameter values "teleport" from scope 1 to scope 2. Meh.
Yup.
If both scoping semantics (Jason's "top of function body" and the one
above) are awkward for different reasons, then maybe there's a better
way to approach default values.
A while ago existential and default operators were discussed, but I
didn't pay much attention. If we have a default operator, then we
could cut default parameter values altogether:
function f(a = g()) {
return a;
function g() {}
}
// is the same as:
function f(a) {
a SOME_DEFAULT_OPERATOR g;
return a;
function g() {}
}
It's not quite as pretty as parameter defaults, but it doesn't suffer
from the scope awkwardness, either.
We don't have default operators in ES6 but we do have default
parameters, which address the most frequently seen use-case. Flipping it
around at this point is bad for two reasons:
* we have to escalate default operator out of strawman and undo the
default parameter work;
* more significant: we have less user testing and frequent-use-case
evidence in favor of the default operator approach;
* the default operator approach is verbose, restating the parameter name
on the LHS.
As an added bonus the loc1 vs. loc2 issue that started the thread
basically goes away.
No, I think not -- that was about the implicit yield in generators, and
a red herring, I think. The real issue is the scope of default
parameters, as you say.
/be
_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss