The class operator: a bridge between object and function exemplers

Russell Leggett russell.leggett at gmail.com
Tue Nov 15 08:16:07 PST 2011


Sorry I'm late to the party, I'm just catching up now. I'm glad that what I
proposed got mentioned (thanks Brendan), but I wanted to be clear that its
not actually what Allen is proposing here. Where Allen is proposing a
simple sugar operator to retrieve the constructor, I was proposing an
operator that does effectively that in the simple case (object literal),
but would create a new constructor function in the more complex case, and
avoid some of the issues being brought up here. Let me go through my logic
a little.

    let Point = class {
         x:0,
         y,0,
         constructor(x,y} {
             this.x=x;
             this.y=y;
         }
    };

In this example, Allen is proposing that object literals with a constructor
property should automatically point back to the object with a .prototype
property. I was assuming current behavior and that the class operator would
perform this, but because it happens before the object is observable, no
harm done.

Here is the crux of what I see as difficult with Allen's approach:

    let Monster = class {
        constructor(name, health) {
            ...
        }
        attack(target) {
            log('The monster attacks ' + target);
        }
    }

    let BossMonster = class Monster <| {
        attack(target){
            log('Boss attacks ' + target);
        }
    }

As has been said, a missing constructor would not result in the expected
behavior. I can also imagine other scenarios where the behavior would be
unusual.

    function makeSpecialClass(obj){
        //perhaps we don't want to modify the original
        let sub = Object.create(obj);
        sub.newMethod = function(){...};
        return class sub;
    }
    ...
    let Specialized = makeSpecialClass(someObj);
    ...
    //or what about
    let f = new Foo();
    f.newMethod = function(){...};
    let Bar = class f;

I think this example is contrived, but illustrates the point that
JavaScript is very dynamic, and sometimes in the building process an object
can be out of sync from its constructor. My expectations when I see this
would be that my results would be a constructor function that can be used
to produce a new version of the UnaryExpression, calling its constructor
code. The best way I can think of to do this would be:

    function classify(obj){
        let sub = obj <| {
            constructor(...args){
                super.constructor(...args);
            }
        }
        sub.constructor.prototype = sub;
        return sub.constructor;
    }

The key is that the UnaryExpression is not modified, and it should still
work even if a constructor is missing. If the UnaryExpression is
unobservable and had an own constructor property I would expect that the <|
portion can be skipped, and the constructor would just be modified directly
to point back at the enclosing object literal.

In regards to Allen's suggestion that the constructor property
automatically point bag to the enclosing object literal, I think that might
be ok, but I think its also brittle, because there are many other cases
where that will likely not be the case such as

    constuctor:function(){...}
    //and
    obj.constructor = function(){...}

ways of building the object. Therefore, leaving the wiring to the class
operator, I think, is more robust.

Furthermore, knowing that class operator does a little more work, and will
often create a new function, I would propose that it also allow:

    class Point {
         ...
    }

without assignment. This could be used to fix the constructor name as
brought up by Brendan.

- Russ
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20111115/8cf0b7ea/attachment.html>


More information about the es-discuss mailing list