When I started trying to articulate why I don't like this idea, I wound up convincing myself that my issue is just that I'm not fond of the ability to return from constructors in the first place for all the reasons we seem to agree on. So I don't like this idea because it furthers something I don't like about existing ES; Thus it became pretty difficult for me to objectively justify the idea that ES6 classes shouldn't return super() by default given that one still can do this in non-default constructors.

OTOH, if ES6 class constructors didn't allow returns, it seems it would justify not doing this much more. When refactoring to classes, this type of behavior should be statically detectable and seems pretty easily worked around via wrapper functions for the majority of cases.

So, if we really want to discourage the return-from-constructor behavior (which I would be very much in favor of), it seems like we should also disallow returns from ES6 class explicit constructors as well.

On 12/28/13, 9:51 AM, Allen Wirfs-Brock wrote:

On Dec 28, 2013, at 5:35 AM, Sebastian Markbåge wrote:

I completely agree that is the intended use and what we should be encouraging people to do. What I'm asking for is to intentionally break best-practices for a specialized use case.

The use case I had in mind was React components. Components in React are described as classes which makes them seem approachable to a broad user base. They cannot and should not be accessed as class instances though. The instances are immutable data structures used exclusively by the library. The base constructor could look something like this:

constructor(x) {
return { _hiddenInstance: this, _instantiationContext: CurrentContext, _id: uid(), _someArgument: x };
}

This would generate a descriptor that can be used by the library but only used as a reference by the user. This allows users to declare classes just like they're used to and even instantiate them normally. However, they'd only be given access to the real instance at the discretion of the library.

With the current ES6 spec. you can accomplish the same thing via:

static [Symbol.create]() {
   return {
_hiddenInstance: super(), //this will create the "normal" instance
        _instantiationContext: CurrentContext,
         _id: uid()
} //this is the object that is passed as the 'this' value to the constructor
};
constructor(x) {
   this._someArgument = x
}


Of course, we could have all users wrap their classes in some kind of decorator constructor and that's probably where we'll end up for clarity. It's would've been a neat pattern though.

    Regarding adding 'return' to the default constructor body.  It
    appears that technically it would be a benign change.  However,
    the only reason to do so would be accommodate superclasses that
    deviate from the above patterns.  In that case, you are probably
    already in the weeds.  I'm not sure that we should be trying to
    facilitate such deviations.


It seems to me that whether we add it or not is arbitrary. By not adding it we're intentionally removing this use case (forever). IMO we need to have a reason to intentionally prevent a use case if it could be easily supported. I'd buy almost any argument here except that it's in bad taste to use this pattern.

If we have reason to believe that this pattern will be harmful, do we also have to do more to prevent normal constructors from returning anything other than "this"?

I'm not exactly sure where who you see ES6 classes fitting into React. Whether you are talking about using them at the meta level to implement React or whether you want to replace React.createClass with something like:

class MyComponent extends React.Component {
   render() { ... }
}

The code I gave above should work in the latter case (although I suspect you are really doing something more complex with the constructor argument). However, to create an instance you would have to say
  new MyComponent({})
instead of
   MyComponent({})

So this makes me think that you may have a different integration in mind. Perhaps:

let MyComponent = React.create(class {...});

I think the topic of who ES6 class definitions (and other features) integrate with frameworks that provide their own abstraction mechanism is an important one so it would be good to explore this further in the context of React.

Allen




_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to