> Granted *using* them would be simpler **if** you didn't care whether > you're calling a constructor vs. non-constructor (e.g., you "just" use
In ES5 the only thing that makes a constructor behave differently is invoking it with `new`. There's no difference between a constructor and a regular function, there's just a different way to invoke it. So yeah - I don't care. > Having `call`/`apply` not work the same way a function call does > (modulo their actual purpose) is a significant departure from how > they've worked since they were added to JavaScript original I see your point but I don't exactly agree. It's not that they work differently, it's just that you aren't allowed to invoke once specific type of function directly. (And again if I had my way, I'd just drop the 'no new' restriction entirely for the sake of 100% backward compatibility between class vs. prototype syntax -- but I don't personally care about the `new` thing). I'd make the counterpoint that the way things are now, we have a much more dramatic departure from the way things worked since the beginning: I can create a function that I have no ability to access directly through any means. There has never been a "black box" process in Javascript before, now there is. I could completely simulate the prototype chain construction process and rewire it any way I wanted, now I can't. This is a big functional and philosophical change. But mostly - from a practical standpoint - it means that "class" syntax is not backwards compatible with prototype syntax. I think that most developers would expect that with the exception of builtins that never worked correctly using the old instantiation patterns, everything else should work interchangeably. You should be able to write simple classes using simple inhertance patterns and have `class` just act as syntactic sugar, unless you're trying to do something that wasn't possible before. I get that a class is not supposed to be exactly the same as a prototype constructor, since one of the goals was to fix the problem extending builtins, but it _should_ be backwards compatible. Right now it's not in a very significant way. > The semantics of `super()` would need to be addressed, in the sense that it too would have to be permitted to use an existing context in this circumstance. This is true. Not being familiar with the implementation details I can't say how big a deal this is, but yes - the ability to pass a context down through `super` (the same as you did old-school by invoking the superclass constructor directly against your own context from within the subclass constructor) is required. To me, this is just backwards compatibility. Thanks again for your time and engagement here. This is a pretty important issue to me, and I'm definitely not knowledgable about the implemenetation details. I am very gratified to be able to get into it here and learn more. On Fri, Jan 6, 2017 at 8:34 AM, T.J. Crowder < [email protected]> wrote: > Note: Related discussion of calling class constructors here: > https://esdiscuss.org/topic/determine-if-a-value-is-callable-constructible > > On Fri, Jan 6, 2017 at 12:11 PM, James Treworgy <[email protected]> > wrote: > > > T.J. Thanks for the very thoughtful analysis. But I keep coming back to > > this: > > > >> since we > >> wouldn't want `call`/`apply` to allow violating the "no `this` before > >> `super(...)`" rule by setting the `this` binding early. > > > > Why? > > > > To me the best solution is also the simplest - just let people do this. > > On first blush, a couple of reasons, but that doesn't mean they aren't > addressable: > > 1. I think the supposed simplicity is illusory. If you get into the > mechanics of actually "just" allowing people to do it with > `call`/`apply`, as I said earlier, I think it looks very like > `Reflect.new` but with less flexbility and with the "`this` before > `super()`" problem. Do you have a proposal for how to actually do it > that doesn't have similar complexity? You'd have to modify `call` and > `apply`, you'd still have to modify how Construct and [[Construct]] > work (at the very least). Maybe you get some savings by allowing a > `this` binding before `super` (you might avoid the hook slot on the > environment), but my instinct is the savings are small change. But I > haven't gone through the same level of analysis on it as I did with > `Reflect.new`, so I'm open to being proved wrong on that. > > Granted *using* them would be simpler **if** you didn't care whether > you're calling a constructor vs. non-constructor (e.g., you "just" use > `call`/`apply`). But is it really the case that there's a lot of code > that doesn't need to care? Calls and construction are very different > things. > > But a win for overloading `call`/`apply` is, of course, that ES5 > constructor code can subclass an ES2015+ class constructor without > branching. Existing ES5 code could be fed an ES2015+ class constructor > and (probably) Just Workâ˘. But I don't know that it's a common use > case outside DI frameworks, which are relatively few and thus > upgradeable. > > 2. Having `call`/`apply` not work the same way a function call does > (modulo their actual purpose) is a significant departure from how > they've worked since they were added to JavaScript originally. Now > every explanation of them must not only say "They call the function > setting a specific value for `this`" but also "**and** they let you > bypass the restriction preventing calling constructors as functions." > Okay, so the counter-argument could be that allowing them to call a > constructor as a function is a by-product of their main purpose > (setting `this`), but to me it's both different and surprising. > > 3. Allowing `this` prior to `super()` in a subclass constructor > depending on how it's called makes it impossible for lint tools and > such to flag that up early as an error. So they can't support the > majority case where that's going to be an error at runtime. > > Perhaps all of those can be addressed or dismissed. I don't want to > give the impression of being married to anything (not that my opinion > is particularly important anyway). But my gut says overloading > `call`/`apply` (thus allowing early `this` binding) isn't markedly > simpler, but is more problematic. > > Side note: In my outline of `Reflect.new`, I should have flagged up > that we'd really want at least the `Reflect.isConstructor` part of > [this proposal](https://github.com/caitp/TC39-Proposals/blob/ > master/tc39-reflect-isconstructor-iscallable.md) > to be in place. DI systems would need to know what they were dealing > with. But (to me, anyway) the `Reflect.isConstructor` part of that > proposal is non-controversial (`Reflect.isCallable` has an open > question about what it should say for class constructors -- how > relevant!). > > I feel like I've done a lot of talking on this; I'm going to hang back > and just listen for a while. :-) > > -- T.J. >
_______________________________________________ es-discuss mailing list [email protected] https://mail.mozilla.org/listinfo/es-discuss

