Two aspects to this: Motivations and syntax. ## On motivations:
Addressing new syntax, the first question has to be: Is this use case sufficiently common and painful that it needs new syntax? The answer may be yes, but we need to ask the question. Trying to solve it without new syntax with a helper function, I've come up with three ways of getting those arguments up front. I'm not all that happy with any of them. ### Helper #1: This kind of has the opposite problem (the class is hidden away at the end), but it's dead simple: ```js this.add(makeInstance("items", itemsModel, class extends ArrayView { populateItem(item) { item.add(new Checkbox("check", new PropertyModel(item.model, "done"))); item.add(new Label("title", new PropertyModel(item.model, "title"))); } })); ``` ...where `makeInstance` is: ```js const makeInstance = (...args) => { return new args[args.length - 1](...args.slice(0, args.length - 1)); }; ``` ### Helper #2: Puts things in the desired order, but isn't exactly elegant at point-of-use: ```js this.add(makeInstance(ArrayView, "items", itemsModel, parent => class extends parent { populateItem(item) { item.add(new Checkbox("check", new PropertyModel(item.model, "done"))); item.add(new Label("title", new PropertyModel(item.model, "title"))); } })); ``` ...where `makeInstance` is: ```js const makeInstance = (parent, ...rest) => { const args = rest.slice(0, rest.length - 1); const subclass = rest[rest.length - 1](parent); return new subclass(...args); }; ``` ### Helper #3: Gets really close in terms of usage, but because the methods would have the wrong [[HomeObject]] (Igor's example didn't use `super` in `populateItem` but presumably it could have), it has to resort to not one but two `setPrototypeOf` calls, which is just ugly: ```js this.add(makeInstance(ArrayView, "items", itemsModel, { populateItem(item) { item.add(new Checkbox("check", new PropertyModel(item.model, "done"))); item.add(new Label("title", new PropertyModel(item.model, "title"))); } })); ``` ...where `makeInstance` is: ```js const makeInstance = (cls, ...rest) => { const args = rest.slice(0, rest.length - 1); const methods = rest[rest.length - 1]; const subclass = class extends cls { }; Object.setPrototypeOf(methods, cls.prototype); Object.setPrototypeOf(subclass.prototype, methods); return new subclass(...args); }; ``` (Hey, I warned you it was ugly.) (This isn't the first time I've wanted to change a method's [[HomeObject]] after creation.) Maybe someone else can do better. Or, of course, just don't use an anonymous class. ## On syntax: Looking at: ```js this.add(new ArrayView("items", itemsModel) { populateItem(item) { item.add(new Checkbox("check", new PropertyModel(item.model, "done"))); item.add(new Label("title", new PropertyModel(item.model, "title"))); } }); ``` A couple of notes/observations: * This is exactly how Java handles [doing the same thing](http://docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html). JavaScript is not Java, of course, but worth noting prior art. * It would be good to hear early from implementers if this presents a parsing challenge. Until the `{`, it looks like you're instantiating `ArrayView` with `"items"` and `itemsModel`; the `{` then changes things. I don't know if that's backtracking, or looking ahead, or what. Obviously Java parsers handle it, but again, different language, different challenges. * If you remove the `this.add(...)` part of that, there's an ASI hazard if you put a line break before the `{` -- it becomes `new ArrayView("items", itemsModel);` followed by a block (which then has invalid content). (Not an insurmountable problem, it's not like it's the only ASI hazard caused by a line break before a `{`. But it would add another one.) -- T.J. Farsight Software Ltd | 20-22 Wenlock Road, London N1 7GU | Company #8393428 tj.crow...@farsightsoftware.com | Direct: +44 (0)20 3627 4231 | Mobile: +44 (0)7717 842 414 If you've received this message in error, please let us know by forwarding it to i...@farsightsoftware.com and then delete it from your system. Please don't copy it or disclose its contents to anyone. Separately, note that email sent over the internet without a digital signature may be modified en route. On Sat, Jan 7, 2017 at 5:35 AM, Igor Vaynberg <igor.vaynb...@gmail.com> wrote: > >> On Jan 6, 2017, at 7:04 PM, Allen Wirfs-Brock <al...@wirfs-brock.com> wrote: >> >> (new class extends foo(bar) {…}) >> is already valid syntax that means use the value return from calling foo >> with argument bar as the superclass of the class that is being instantiated. >> What you propose would be a breaking change. > > What about limiting it just to (new foo(bar) {...}) syntax? > > -igor > > _______________________________________________ > es-discuss mailing list > es-discuss@mozilla.org > https://mail.mozilla.org/listinfo/es-discuss _______________________________________________ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss