es-discuss Digest, Vol 56, Issue 4

Russell Leggett russell.leggett at gmail.com
Sat Oct 1 14:31:53 PDT 2011


On Sat, Oct 1, 2011 at 3:42 PM, Axel Rauschmayer <axel at rauschma.de> wrote:
> Note that in JavaScript terminology, a class is a function (which in turn is
> an object). So there really are no classes. Just functions that produce
> instances when used with the "new" operator (if a function is used this way,
> it is often called a constructor).

I'm fully aware of this - that's why I tried to remember to aways use
"class" in parens because its not really classes.

>Then the difficulty is how to assemble it
> all:
> 1. The super-constructor SuperClass must be the prototype of the
> sub-constructor ClassName, if class properties are to be inherited.
> 2. The super-prototype SuperClass.prototype must be the the prototype of
> ClassName.prototype.
> 3. (Instance) methods must be added to ClassName.prototype.
> 4. Class properties must be properties of ClassName (which is a function!).
> 5. Instance properties must be set up in the constructor.
> If you look at Allen’s class pattern then the proto operator <| takes care
> of #1 + #2, .prototype.{} does #3, .constructor.{} does #4. You have to make
> sure that the compound expression ends with something that returns the
> constructor, or else the assignment at the beginning makes no sense.
> If you want to read up on this – a while ago, I’ve written a post that might
> be helpful: http://www.2ality.com/2011/06/prototypes-as-classes.html

Yes, I included the pattern in the email I sent to show it as a
reference. When I supplied my version of the pattern, I was not trying
to say that the pattern would work as is, but rather that it should be
possible to make the operator capable of also working to create a nice
class pattern. This is why I said it would be an additional overload
to the operator.

According to the original pattern:

       const className = superClass <| function(/*constructor parameters */) {
         //constructor body
         super.constructor(/*arguments to super constructor */);
         this.{
          //per instance property definitions
         };
       }.prototype.{
         //instance properties defined on prototype
       }.constructor.{
         //class (ie, constructor) properties
       };

We take superClass (a constructor function) and we use it as the
prototype of the new constructor function on the RHS, then we use
chaining to update the prototype, then update constructor. As you say,
you have to be careful of returning the constructor (even if not
modified) to make this chaining work. While I think this is already an
improvement, its still complicated enough that we're working on more
sugar for it. What I was suggesting was that if the LHS was a
constructor function, and the RHS was an object literal, then:

       const ClassName = SuperClass <| {
               constructor(/*constructor parameters */) {
                  //constructor body
                  super.constructor(/*arguments to super constructor */);
                  this.{
                    //per instance property definitions
                  }
               }
               method1(){ return super.method1(); }
               method2(){}
               prop1:"Properties unlikely, but allowed"
       }.{
               //class properties
               staticMethod(){}
       };

1. If a "constructor" method is supplied as part of the object
literal, it will be used as the new constructor, and take the LHS
constructor as its prototype. If not, an new empty constructor will be
created instead and take the LHS constructor as its prototype.
2. The rest of the object literal will be used as the new constructors
prototype, and it will use the LHS's prototype as it's prototype.
3. The result of the <| operand in my example would be the new
class/constructor function, so it can be assigned to "const ClassName"
or as in my example, the .{ operator can be used to add class methods
and still return the correct result.

- Russ


More information about the es-discuss mailing list