Re: Proposal For A New Alternative Keyword To “this” For Classes

Ranando King kingmph at
Tue Mar 12 18:36:06 UTC 2019

@Isiah Remember, the class-fields proposal has absorbed the private-fields
proposal, and it is those private fields that have no precise equivalent.
WeakMap and closures can approximate what private fields do. However,
private fields has semantics and capabilities that cannot be fully
reproduced in current ES. For instance, I can wrap both WeakMap and Proxy
in a way that Babel private-fields will be proxy safe. With native private
fields, that's impossible.

On Tue, Mar 12, 2019 at 10:39 AM Isiah Meadows <isiahmeadows at>

> @Ranando Minor nit: class fields can be purely implemented in terms of
> `defineProperty` (for public) and weak maps (for private - what's used
> today for private data). Private methods could be implemented in terms of
> weak sets/maps and an object with methods outside the class's scope.
> Private static properties could just verify `this === Type`.
> So no, those don't quite reify classes, either. (If something can be fully
> transpiled or polyfilled, it doesn't create or reify any new primitives.)
> On Tue, Mar 12, 2019 at 09:51 Ranando King <kingmph at> wrote:
>> I get what you're after. I touched on the same things when creating my
>> private members proposal. The best of approaches for what you want is
>> indeed relying on the lexical scope to act as a binding for all class
>> members. There's just a couple of problems with doing things that way:
>> 1. ES is a dynamic language. This makes lexical binding difficult because
>> it's entirely possible to call a non-static class method where *this* is
>> undefined or null. Not allowing for that scenario will break existing code.
>> Allowing for that scenario will cause variables to be unexpectedly either
>> written to the global scope or throw.
>> 2. Class isn't really a "thing" in ES, at least, it isn't until
>> class-fields lands. The use of the *class* keyword is currently
>> completely optional. There's nothing in current ES that you can do with
>> *class* that can't be done without it except use the *super()* call in
>> the constructor function. But even that can be substituted with
>> *Reflect.construct*(). Class-fields will destroy this symmetry, making
>> *class* it's own unique "thing". But until then, what do you do about
>> all the "classes" that don't use the *class* keyword?
>> Long and short, this means both the lexical scope approach and the
>> alternate keyword approach will either break existing code or bring
>> dubious-to-no benefit.
>> On Tue, Mar 12, 2019 at 3:06 AM john larson <johnlarsondev1 at>
>> wrote:
>>> So in terms of implementation, may be having instance method/property
>>> references on the objects and having static method/property references on
>>> the prototype is the solution?
>>> On Tue, Mar 12, 2019 at 8:14 AM Isiah Meadows <isiahmeadows at>
>>> wrote:
>>>> I've done a little engine work, and inline caches work by inline type
>>>> maps based on the callee site. This *can* be used to reconstruct values +
>>>> receivers, but only when the value is constant. It is not sufficient to
>>>> ensure identity remains the same, and engines would still need a weak map
>>>> to link methods to instances (as opposed to prototypes).
>>>> It's worth noting not even Java or Ruby offers this - their method
>>>> references/objects (like our bound functions) are *not* memoized - they're
>>>> linked to classes, not instances. Python is the exception here in
>>>> auto-binding instance methods, not the norm.
>>>> On Mon, Mar 11, 2019 at 15:37 Bergi <a.d.bergi at> wrote:
>>>>> Hi John!
>>>>> > I think the js run-time already has that information at hand, so as
>>>>> > long as we don't implement this as pure syntactical sugar, there
>>>>> would
>>>>> > not be a need to keep an extra reference to anything, because it
>>>>> would
>>>>> > be already there. The run-time will know which instance the invoked
>>>>> > method belongs to.
>>>>> Well no, you're wrong here: the runtime does not have this information
>>>>> at hand. In your example (simplified)
>>>>> ```
>>>>> var reqManager = new RequestManager();
>>>>> function addEventListener(f) {
>>>>>      console.log(f);
>>>>>      f(event);
>>>>> }
>>>>> addEventListener(reqManager.responseHandler);
>>>>> ```
>>>>> the `addEventListener` function will not know that the function `f` you
>>>>> passed was a method of the `reqManager` instance. It cannot distinguish
>>>>> that call from
>>>>> ```
>>>>> addEventListener(RequestManager.prototype.responseHandler);
>>>>> ```
>>>>> or
>>>>> ```
>>>>> var g = otherReqManager.responseHandler;
>>>>> addEventListener(g);
>>>>> ```
>>>>> It is exactly the same function that is passed in all three cases.
>>>>> There
>>>>> is no instance bound to `f`, and `f(event)` will not invoke it as a
>>>>> method (with a receiver/`this` value).
>>>>> Best regards,
>>>>>   Bergi
>>>>> _______________________________________________
>>>>> es-discuss mailing list
>>>>> es-discuss at
>>>> _______________________________________________
>>>> es-discuss mailing list
>>>> es-discuss at
>>> _______________________________________________
>>> es-discuss mailing list
>>> es-discuss at
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the es-discuss mailing list