Closed patrick-soquet closed 4 years ago
The hang-up is a matter of semantics. Here's a translation of the class you gave that should explain why:
function f() {
return class {
constructor() {
//super goes here if needed
(() => {
Object.defineProperties(this, "field", {
enumerable: true,
configurable: true,
writable: true,
value: arguments //"strict mode" doesn't allow arguments
});
})();
//other initializer functions here if they exist
//constructor body code goes here if it exists
}
}
}
As you can see, the issue is that each initializer is essentially wrapped in a separate function and called from the scope of the constructor. That's also the reason that you can't use new.target
in an initializer.
I can't speak for the whole committee's reasoning, but here's why I think it makes sense to ban arguments
in initializers.
First, at a surface level: We decided to ban arguments
because arguments
was not going to give people what they expected. Following the general principles of lexical scoping, arguments
was either going to either be an empty arguments list (if we considered each initializer to be its own method, scope-wise), or the enclosing binding of arguments
(if we just fell back to the default, as computed property keys and the extends
clause do).
But I guess the real question is, why not give the arguments value that would be more useful, the one passed into the constructor? I think the general idea of lexical scoping would be that these things are only set within the particular curly braces/parameter list where the function is defined. It's weird enough that arguments
is set without being textually present; if we also defined it in a few other places that aren't even linearly adjacent, it'd be even weirder.
In the course of developing the class fields proposal, we did lament how constructor arguments are unavailable. We looked into several different syntactic alternatives, but eventually concluded that the syntax used in TypeScript and Babel (field = initializer
in the class body) was for the best. (Well, this is only part of the syntax TS supports, and I do like some of the other parts, but it's hard to see how to carry them over here.)
As an aside, arguments
is considered a legacy construct, and rest arguments are preferred instead for more intuitive coding patterns. It'd really be too bad if arguments
were the only way to get at constructor parameters. But it doesn't seem like that was really an option anyway.
@littledan Thank you much for your detailed explanation. FWIW, fields, especially private fields have been really welcomed in XS. Hopefully the proposal will be stage 4 soon.
Preventing field initializers to contain
arguments
required special care in the specification and the implementations. A developer asked me why this code is wrong:while this code is right:
I searched for an explanation but did not find one. What are we trying to prevent here? Thank you