Allen Wirfs-Brock (2013-12-28T17:51:53.000Z)
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


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20131228/4c4383e6/attachment.html>
domenic at domenicdenicola.com (2014-01-08T19:51:51.554Z)
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:
> 
> ```js
> 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:

```js
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:

```js
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 

```js
new MyComponent({})
```

instead of 

```js
MyComponent({})
```

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

```js
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.