An "extend" operator is a natural companion to <|

Brendan Eich brendan at mozilla.com
Tue Jul 19 11:16:05 PDT 2011


On Jul 19, 2011, at 11:07 AM, Bob Nystrom wrote:

> This is probably a terrible idea, but in the interest of considering all options,

Not terrible at all, and thanks for considering more options. I claim that is what es-discuss is for, so long as you've thought out the pitch and checked to avoid rehashing.


> we could do something like:
>  
> class Point {
>   constructor(x, y) {
>     this.x = x;
>     this.y = y;
>   }
> 
> class:
>   zero() {
>     return new Point(0, 0);
>   }
> 
>   unit() {
>     return new Point(1, 1);
>   }
> 
> prototype:
>   manhattanDistance() {
>     return Math.abs(this.x) + Math.abs(this.y);
>   }
> }

I'm used to C++, so I buy it. Also, and more important, it avoids the gratuitous over-indentation tax on either class or prototype elements.


> So, class: and prototype: indicate that members declared after them go into those objects, much like public: and private: in a class in C++. By default, it assumes prototype: since that's where most members go. In this example here, I'm switching back and forth just to show the idea, but idiomatic code would likely be:
> 
> class Point {
>   constructor(x, y) {
>     this.x = x;
>     this.y = y;
>   }
> 
>   manhattanDistance() {
>     return Math.abs(this.x) + Math.abs(this.y);
>   }

Right, default is prototype: to match the predominance of prototype "instance" methods over class methods.


> class:
>   zero() {
>     return new Point(0, 0);
>   }
> 
>   unit() {
>     return new Point(1, 1);
>   }
> }
> 
> (It may be that we should use constructor: or static: instead of class:.)

Those hurt more. I like class, it is shortest and closest to the keyword that introduces the binding (in the named form, not for class expressions -- but those want a connection back to the keyword too).


> That solves the double indentation problem.

Right!


> We could possibly extend this to handle declaratively specifying instance members and/or public/private too:
> 
> class Monster {
>   constructor(name, health) {
>     this.name = name;
>     this.health = health;
>   }
>  
>   attack(target) {
>     log('The monster attacks ' + target);
>   }
>  
>   // The contextual keyword "get" followed by an identifier and
>   // a curly body defines a getter in the same way that "get"
>   // defines one in an object literal.
>   get isAlive() {
>     return this.health > 0;
>   }
>  
>   // Likewise, "set" can be used to define setters.
>   set health(value) {
>     if (value < 0) {
>       throw new Error('Health must be non-negative.')
>     }
>     this.health = value
>   }
> 
> // "new" lets you declare members on new instances. these would presumably be
> // invoked on the new object before the constructor body is run.
> new:
>   numAttacks = 0;
>   // declaring an instance property here mainly so you can document it. could be
>   // useful later for guards or other annotations.
>   name;

Neat idea, although the assignment expression-statement appearance still rankles. It looks like statements are allowed there, rather than declaration forms of some sort. OTOH we are talking about properties, and declarations are in ES.next lexical binding forms if you exclude object literal property assignments from "declarations".


> // "private" before a section lets you declare private members on that object.
> private new:
>   health;

Not sure we need 'new' there given lack of private prototype properties in the proposal. It's a bit verbose. Probably even if we add private prototype properties we can let private: (in this idea you've pitched) default to private instance.


> class:
>   create(name) {
>     let health = Math.random(5, 20);
>     return new Monster(name, health);
>   }
>  
>   const attackMessage = 'The monster hits you!';
> }
> 
> Strangely, I don't find myself hating this as much as I expected. <shrug>

No, don't <shrug>, <cheer>. I think what you've suggested here is strictly better than (a) over-indenting one or another group of elements; (b) putting "instance variable" declarations in magic syntax in the constructor body; (c) festooning one's class declaration with repeated "static" prefix keywords.

I think this wins, so far. This does suggest we rushed classes in prematurely. I'm not saying anything more than that we should take our time and avoid marrying the syntax in the proposal. We already have agreed that private(this), private(foo), etc. is straw to burn up.

/be
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20110719/6be1bb4f/attachment.html>


More information about the es-discuss mailing list