Look Ma, no "this" (was: ECMAScript Harmony)

Brendan Eich brendan at mozilla.org
Mon Aug 25 11:28:41 PDT 2008


On Aug 25, 2008, at 12:34 AM, Peter Michaux wrote:

> On Sun, Aug 24, 2008 at 9:44 PM, Kris Zyp <kris at sitepen.com> wrote:
>
>> Desugared from:
>
>> class Point {
>>   private var x = Math.random();
>>   function getX(){
>>       return this.x;
>>   }
>>   ...
>> }
>
> Is there any need for the "this."? Some languages allow "this.x" to
> get out from under the shadow of a local "x" inside "getX". I don't
> think it is necessary to be able to escape such shadowing and actually
> increases confusion. If a method is many lines long then the reader
> may forget that "x" is local and not the instance variable. I would
> just call the local variable "locx" or "xx" or something different. I
> would actually rather see the "this." shadow escaping be disallowed.

That might be a good idea.

The bigger question is whether |this| remains at all. The desugarings  
we tend to write on whiteboards use |let self = ...| or similar and | 
self| as the new |this| -- but of course that might collide with a  
necessary inner or outer name. It would be better to gensym the name,  
but who has time at a whiteboard?

To refer to the instance in the sugared language, and there are valid  
use-cases for doing so, we should use |this|. There's no point in  
introducing a new keyword. Which gets to a point you raise later,  
about var in class being confusing. If class is the new, higher  
integrity constructor function that induces instance-bound frozen  
methods, etc., then its syntax (by the similarity principle I  
adumbrated earlier) *should* mimic function:

class Point(x, y) { // parameters to constructor here
   let r = Math.sqrt(x*x + y*y);
   let theta = Math.atan2(y, x);
   function getX() x;
   function getY() y;
   // etc.
}

var or const could be used too, because they can be used in function  
bodies. Class body *is* constructor code. Similarity is good because  
it builds on JS programmers' knowledge of functions, but provides  
incrementally better semantics for the similar syntax. Programmers  
get the carrot, not the stick of gratuitously different syntax.

It will take more than a 2D point class to make the case, but this  
was along the lines of the Oslo discussions on the third day, to  
desugar as Mark proposed on the first (and showed in his post at the  
head of this thread).


> In the above code snip it seems that properties will be public unless
> listed as private. In the security world, whitelisting is considered a
> best practice as blacklisting can accidentally leave things out in
> public that should not be.

Not everything in JS is security-critical. JS is used in single-trust- 
domain embeddings, but even on the web, the B&D programming by way of  
the security root password to the tattered "just a scripting  
language" constitution seems like a power-grab :-P. I mixed three  
kinds of technical politics there, but they are all relevant.  
Different parties are concerned about the common good, but we don't  
all agree on the common good.

Python and Smalltalk don't have private methods by default (or at  
all), just to pick two examples. Should classes as better  
constructors have this bias?

I'm not saying "no", I reserve judgment. It seems to me much depends  
on the module system, if there is one (and there had better be, since  
in spite of being the inevitable source of addressing and loading  
semantics, the <script> tag is not enough for in-language modularity).


> What about the following two options:
>
> class Point {
>    private x = Math.random();
>    public function getX(){
>        return x;
>    };
> }

Verbose, please pick a default. Making people type private all the  
time is going to get old (if you think 'function' is too long...).


> var Point = class {
>    private x = Math.random();
>    public getX = function(){
>        return x;
>    };
> };

This shows a separable and good idea: first-class classes. BTW, you  
probably want 'const Point = class { ... }', and 'class Point...'  
should make a const binding by default (unlike a function definition  
-- another upgrade).

Another separable point to debate: resolved, classes should freely  
nest (in other classes and functions) and generate new entities each  
time they are evaluated. Just like functions (ignoring or removing  
the joined function object option from ES3).


> If only one option could be included I'd *much* prefer the final
> option as "var" could be changed to "let" so I control the class's
> scope better.

That's not to say we shouldn't have the named form of class, any more  
than we shouldn't have named functions. Named functions are a special  
form, as close to let rec as you get in JS. You can have mutually  
recursive named functions call one another freely, making forward  
refs, due to hoisting.

You also get the intrinsic name, useful for diagnostics at runtime  
and harder to infer (really guess, worst-case pick the name of the  
most relevant binding) for anonymous functions.


> In either of the last two cases, I imagine that the "Point" variable
> is pointing to a first-class class objects (which desugars to a
> constructor function) that I could pass around, yes?

Yes.

There are deeper waters to do with types, but this is enough for  
classes. Other details need to be worked out, but this is enough to  
chew on for now. Thanks,

/be


More information about the Es-discuss mailing list