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

classic Classic list List threaded Threaded
29 messages Options
12
Reply | Threaded
Open this post in threaded view
|

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

john larson

Summary of the problem:

“this” keyword in Javascript is context dependent. And this is one of the culprits of most subtle and latent errors in Javascript. Moreover, use of “this” cannot be avoided if we are using classes and trying to reference instance properties.

When “this” is used in callback functions or in functions given to forEach as argument, IDEs rightfully cannot raise any design-time errors, giving developers the false sense of security, but we get run-time errors because “this” is undefined.

There seem to be two work-arounds:

1.      Using arrow functions

2.      Using .bind(this) syntax

Just assuming we forgot to use an arrow function or a .bind(), the IDE will not be able to raise an error and we will encounter the error in run-time.

 

What I propose:

I am proposing a new keyword that will be the alternative of "this" and will always point to the instance of the class. The name of the new keyword can be chosen with consensus from the community such that it would minimize/eliminate collision in existing codebases.

 

Here is a sample js code:

 

class RequestManager{
 
    constructor(){
        this.successMessage = "Xhr successful.";
    }
 
 
    makeRequest() {
        var oReq = new XMLHttpRequest();
        oReq.addEventListener("load", this.responseHandler);
        oReq.open("GET", "www.google.com");
        oReq.send();
    }
 
    responseHandler() {
        window.alert(this.successMessage);
    }
}
 
var reqManager = new RequestManager();
reqManager.makeRequest();

 

This piece of code will alert “undefined” because “this” is undefined in the callback function in strict mode.

Now let’s assume a new keyword is used insetead of “this” that will always point to the class instance.

As per its implementation, as described on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes:

JavaScript classes, introduced in ECMAScript 2015, are primarily syntactical sugar over JavaScript's existing prototype-based inheritance. The class syntax does not introduce a new object-oriented inheritance model to JavaScript.”

So with the new keyword introduced, behind the scenes, previous class could be interpreted as a piece of code along the lines of:

 

var RequestManager = function () {
    var self = this;
    self.successMessage = "Xhr successful";
 
    self.makeRequest = function () {
        var oReq = new XMLHttpRequest();
        oReq.addEventListener("load", responseHandler);
        oReq.open("GET", "www.google.com");
        oReq.send();
    };
 
    var responseHandler = function () {
        window.alert(self.successMessage);
    };
};
var reqManager = new RequestManager();
 
reqManager.makeRequest();

 

I believe this way, we would not have to resort to work-arounds for such a fundamental construct of the language and this would ease developers’ lives as someone forgetting to have used an arrow function or the .bind(this) syntax will not be a problem anymore.

 

Best Regards,

John


Virus-free. www.avast.com

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

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

Bergi
Hi John,
I don't think we do need another keyword for this. People would forget
to use that new keyword instead of using this, just like they currently
forget to use arrow functions.
That said, your desired "behind-the-scenes implementation" can already
be achieved easily with the class fields proposal and an arrow function.
However, [there are many problems with that
approach](https://medium.com/@charpeni/arrow-functions-in-class-properties-might-not-be-as-great-as-we-think-3b3551c440b1)
anyway.

kind regards,
  Bergi
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

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

john larson
Hi Bergi,

Thanks for your input. I believe that it would be a trivial task for current static code analyzers to restrict usage of "this" for anyone opting in to use this new keyword exclusively. But the same does not hold true for other work-arounds such as arrow functions. And in addition to that, as you mentioned, arrow functions might have their own problems. Wouldn't such an alternative keyword be a good addition to our toolkit anyway?

Best Regards,
John

Virus-free. www.avast.com

On Sat, Mar 9, 2019 at 5:18 PM Bergi <[hidden email]> wrote:
Hi John,
I don't think we do need another keyword for this. People would forget
to use that new keyword instead of using this, just like they currently
forget to use arrow functions.
That said, your desired "behind-the-scenes implementation" can already
be achieved easily with the class fields proposal and an arrow function.
However, [there are many problems with that
approach](https://medium.com/@charpeni/arrow-functions-in-class-properties-might-not-be-as-great-as-we-think-3b3551c440b1)
anyway.

kind regards,
  Bergi
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

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

Bergi
Hi John,

> I believe that it would be a trivial task for
> current static code analyzers to restrict usage of "this" for anyone
> opting in to use this new keyword exclusively.

Static tooling, like the TypeScript compiler, can detect problematic
method usage already today. Sure, having a dedicated syntax for this
will make static analysis simpler, but I don't deem that a worthy
addition to the language.

> As you mentioned, arrow functions might have their own
> problems. Wouldn't such an alternative keyword be a good addition to our
> toolkit anyway?

What I was trying to say is that your proposed alternative has exactly
the same problems as instance-member arrow functions have today.

Best regards,
  Bergi
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

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

Jordan Harband
An additional keyword like this would require a function to have a hidden reference back to the instance. However, especially for `class` methods, but also for ES5-style inheritance, or even for `class Foo {} Foo.prototype.bar = function () {}`, methods are *shared*. You might have a billion instances, but only one function that uses your new keyword - how would the engine know which instance you were referring to?

On Sat, Mar 9, 2019 at 7:50 AM Bergi <[hidden email]> wrote:
Hi John,

> I believe that it would be a trivial task for
> current static code analyzers to restrict usage of "this" for anyone
> opting in to use this new keyword exclusively.

Static tooling, like the TypeScript compiler, can detect problematic
method usage already today. Sure, having a dedicated syntax for this
will make static analysis simpler, but I don't deem that a worthy
addition to the language.

> As you mentioned, arrow functions might have their own
> problems. Wouldn't such an alternative keyword be a good addition to our
> toolkit anyway?

What I was trying to say is that your proposed alternative has exactly
the same problems as instance-member arrow functions have today.

Best regards,
  Bergi
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

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

john larson
Although the method lives on the prototype, the engine should already have knowledge of the object whose method is being invoked. I am not an expert on the internal workings of the engine, so I would be glad if anyone would correct me on this if I am wrong.

Virus-free. www.avast.com

On Sun, Mar 10, 2019 at 12:27 AM Jordan Harband <[hidden email]> wrote:
An additional keyword like this would require a function to have a hidden reference back to the instance. However, especially for `class` methods, but also for ES5-style inheritance, or even for `class Foo {} Foo.prototype.bar = function () {}`, methods are *shared*. You might have a billion instances, but only one function that uses your new keyword - how would the engine know which instance you were referring to?

On Sat, Mar 9, 2019 at 7:50 AM Bergi <[hidden email]> wrote:
Hi John,

> I believe that it would be a trivial task for
> current static code analyzers to restrict usage of "this" for anyone
> opting in to use this new keyword exclusively.

Static tooling, like the TypeScript compiler, can detect problematic
method usage already today. Sure, having a dedicated syntax for this
will make static analysis simpler, but I don't deem that a worthy
addition to the language.

> As you mentioned, arrow functions might have their own
> problems. Wouldn't such an alternative keyword be a good addition to our
> toolkit anyway?

What I was trying to say is that your proposed alternative has exactly
the same problems as instance-member arrow functions have today.

Best regards,
  Bergi
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

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

Jordan Harband
The engine only has that knowledge when you call it in `a.b()` form - at which point, `this` is already the instance. For a keyword to not be context dependent, it'd have to be the instance even when you'd done something like `const { b } = a; b()`. To do this would require either a) `a` has its own distinct copy of `b` that's bound to `a`, or b) `a.b` to be a getter that does that binding upon request.

Constructor-binding, field-binding, or arrow function fields all work the same way - they create a separate copy of a function for *each and every* instance, so that the function can point back to the instance even when extracted off of the object.

I'm not clear on how there'd be any other way to do it.

On Sat, Mar 9, 2019 at 1:41 PM john larson <[hidden email]> wrote:
Although the method lives on the prototype, the engine should already have knowledge of the object whose method is being invoked. I am not an expert on the internal workings of the engine, so I would be glad if anyone would correct me on this if I am wrong.

Virus-free. www.avast.com

On Sun, Mar 10, 2019 at 12:27 AM Jordan Harband <[hidden email]> wrote:
An additional keyword like this would require a function to have a hidden reference back to the instance. However, especially for `class` methods, but also for ES5-style inheritance, or even for `class Foo {} Foo.prototype.bar = function () {}`, methods are *shared*. You might have a billion instances, but only one function that uses your new keyword - how would the engine know which instance you were referring to?

On Sat, Mar 9, 2019 at 7:50 AM Bergi <[hidden email]> wrote:
Hi John,

> I believe that it would be a trivial task for
> current static code analyzers to restrict usage of "this" for anyone
> opting in to use this new keyword exclusively.

Static tooling, like the TypeScript compiler, can detect problematic
method usage already today. Sure, having a dedicated syntax for this
will make static analysis simpler, but I don't deem that a worthy
addition to the language.

> As you mentioned, arrow functions might have their own
> problems. Wouldn't such an alternative keyword be a good addition to our
> toolkit anyway?

What I was trying to say is that your proposed alternative has exactly
the same problems as instance-member arrow functions have today.

Best regards,
  Bergi
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

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

Michael Luder-Rosefield
How about binding `this` to a variable in the constructor? The following syntax throws an error due to `this` being a reserved word, so won't break any existing code:

```
class Foo {
  constructor (this: self, /* normal args */) {
    // ...
  }
}
```

I can see arguments against that as it breaks the convention for how parameter lists work, and also requires a constructor. Perhaps, then, we could either use something like a modified version of class field declarations to make class variables:

```
class Foo {
  const self = this;
  // ...
}
```

Or, maybe, allow parentheses before the class body to define variables:

```
class Foo (this: self) {
  //...
}
```

No, I don't like that one either. 

The second suggestion (class variables as extension of class fields proposal) seems like it has potential to me, so it seems like an excellent time for everyone here to tell me why it's awful and stupid.

On Sun, 10 Mar 2019 at 06:59 Jordan Harband <[hidden email]> wrote:
The engine only has that knowledge when you call it in `a.b()` form - at which point, `this` is already the instance. For a keyword to not be context dependent, it'd have to be the instance even when you'd done something like `const { b } = a; b()`. To do this would require either a) `a` has its own distinct copy of `b` that's bound to `a`, or b) `a.b` to be a getter that does that binding upon request.

Constructor-binding, field-binding, or arrow function fields all work the same way - they create a separate copy of a function for *each and every* instance, so that the function can point back to the instance even when extracted off of the object.

I'm not clear on how there'd be any other way to do it.

On Sat, Mar 9, 2019 at 1:41 PM john larson <[hidden email]> wrote:
Although the method lives on the prototype, the engine should already have knowledge of the object whose method is being invoked. I am not an expert on the internal workings of the engine, so I would be glad if anyone would correct me on this if I am wrong.

Virus-free. www.avast.com

On Sun, Mar 10, 2019 at 12:27 AM Jordan Harband <[hidden email]> wrote:
An additional keyword like this would require a function to have a hidden reference back to the instance. However, especially for `class` methods, but also for ES5-style inheritance, or even for `class Foo {} Foo.prototype.bar = function () {}`, methods are *shared*. You might have a billion instances, but only one function that uses your new keyword - how would the engine know which instance you were referring to?

On Sat, Mar 9, 2019 at 7:50 AM Bergi <[hidden email]> wrote:
Hi John,

> I believe that it would be a trivial task for
> current static code analyzers to restrict usage of "this" for anyone
> opting in to use this new keyword exclusively.

Static tooling, like the TypeScript compiler, can detect problematic
method usage already today. Sure, having a dedicated syntax for this
will make static analysis simpler, but I don't deem that a worthy
addition to the language.

> As you mentioned, arrow functions might have their own
> problems. Wouldn't such an alternative keyword be a good addition to our
> toolkit anyway?

What I was trying to say is that your proposed alternative has exactly
the same problems as instance-member arrow functions have today.

Best regards,
  Bergi
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

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

Jordan Harband
There'd still have to be a way for an arbitrary function - which (unless called in `a.b()` form) has no guaranteed connection back to `a` - to have a reference back to the object.

On Sat, Mar 9, 2019 at 10:57 PM Michael Luder-Rosefield <[hidden email]> wrote:
How about binding `this` to a variable in the constructor? The following syntax throws an error due to `this` being a reserved word, so won't break any existing code:

```
class Foo {
  constructor (this: self, /* normal args */) {
    // ...
  }
}
```

I can see arguments against that as it breaks the convention for how parameter lists work, and also requires a constructor. Perhaps, then, we could either use something like a modified version of class field declarations to make class variables:

```
class Foo {
  const self = this;
  // ...
}
```

Or, maybe, allow parentheses before the class body to define variables:

```
class Foo (this: self) {
  //...
}
```

No, I don't like that one either. 

The second suggestion (class variables as extension of class fields proposal) seems like it has potential to me, so it seems like an excellent time for everyone here to tell me why it's awful and stupid.

On Sun, 10 Mar 2019 at 06:59 Jordan Harband <[hidden email]> wrote:
The engine only has that knowledge when you call it in `a.b()` form - at which point, `this` is already the instance. For a keyword to not be context dependent, it'd have to be the instance even when you'd done something like `const { b } = a; b()`. To do this would require either a) `a` has its own distinct copy of `b` that's bound to `a`, or b) `a.b` to be a getter that does that binding upon request.

Constructor-binding, field-binding, or arrow function fields all work the same way - they create a separate copy of a function for *each and every* instance, so that the function can point back to the instance even when extracted off of the object.

I'm not clear on how there'd be any other way to do it.

On Sat, Mar 9, 2019 at 1:41 PM john larson <[hidden email]> wrote:
Although the method lives on the prototype, the engine should already have knowledge of the object whose method is being invoked. I am not an expert on the internal workings of the engine, so I would be glad if anyone would correct me on this if I am wrong.

Virus-free. www.avast.com

On Sun, Mar 10, 2019 at 12:27 AM Jordan Harband <[hidden email]> wrote:
An additional keyword like this would require a function to have a hidden reference back to the instance. However, especially for `class` methods, but also for ES5-style inheritance, or even for `class Foo {} Foo.prototype.bar = function () {}`, methods are *shared*. You might have a billion instances, but only one function that uses your new keyword - how would the engine know which instance you were referring to?

On Sat, Mar 9, 2019 at 7:50 AM Bergi <[hidden email]> wrote:
Hi John,

> I believe that it would be a trivial task for
> current static code analyzers to restrict usage of "this" for anyone
> opting in to use this new keyword exclusively.

Static tooling, like the TypeScript compiler, can detect problematic
method usage already today. Sure, having a dedicated syntax for this
will make static analysis simpler, but I don't deem that a worthy
addition to the language.

> As you mentioned, arrow functions might have their own
> problems. Wouldn't such an alternative keyword be a good addition to our
> toolkit anyway?

What I was trying to say is that your proposed alternative has exactly
the same problems as instance-member arrow functions have today.

Best regards,
  Bergi
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

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

Michał Wadas
In reply to this post by john larson
This is solvable with decorators or getters.

class Foo {

@cached
get method() {
    return () => this.foobar();
}

}

class Bar {

@bound
method() {
   return this.foobar();
}

}

Definitions for decorators @bound and @cached are pretty trivial.

On Sat, Mar 9, 2019 at 12:42 PM john larson <[hidden email]> wrote:

Summary of the problem:

“this” keyword in Javascript is context dependent. And this is one of the culprits of most subtle and latent errors in Javascript. Moreover, use of “this” cannot be avoided if we are using classes and trying to reference instance properties.

When “this” is used in callback functions or in functions given to forEach as argument, IDEs rightfully cannot raise any design-time errors, giving developers the false sense of security, but we get run-time errors because “this” is undefined.

There seem to be two work-arounds:

1.      Using arrow functions

2.      Using .bind(this) syntax

Just assuming we forgot to use an arrow function or a .bind(), the IDE will not be able to raise an error and we will encounter the error in run-time.

 

What I propose:

I am proposing a new keyword that will be the alternative of "this" and will always point to the instance of the class. The name of the new keyword can be chosen with consensus from the community such that it would minimize/eliminate collision in existing codebases.

 

Here is a sample js code:

 

class RequestManager{
 
    constructor(){
        this.successMessage = "Xhr successful.";
    }
 
 
    makeRequest() {
        var oReq = new XMLHttpRequest();
        oReq.addEventListener("load", this.responseHandler);
        oReq.open("GET", "www.google.com");
        oReq.send();
    }
 
    responseHandler() {
        window.alert(this.successMessage);
    }
}
 
var reqManager = new RequestManager();
reqManager.makeRequest();

 

This piece of code will alert “undefined” because “this” is undefined in the callback function in strict mode.

Now let’s assume a new keyword is used insetead of “this” that will always point to the class instance.

As per its implementation, as described on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes:

JavaScript classes, introduced in ECMAScript 2015, are primarily syntactical sugar over JavaScript's existing prototype-based inheritance. The class syntax does not introduce a new object-oriented inheritance model to JavaScript.”

So with the new keyword introduced, behind the scenes, previous class could be interpreted as a piece of code along the lines of:

 

var RequestManager = function () {
    var self = this;
    self.successMessage = "Xhr successful";
 
    self.makeRequest = function () {
        var oReq = new XMLHttpRequest();
        oReq.addEventListener("load", responseHandler);
        oReq.open("GET", "www.google.com");
        oReq.send();
    };
 
    var responseHandler = function () {
        window.alert(self.successMessage);
    };
};
var reqManager = new RequestManager();
 
reqManager.makeRequest();

 

I believe this way, we would not have to resort to work-arounds for such a fundamental construct of the language and this would ease developers’ lives as someone forgetting to have used an arrow function or the .bind(this) syntax will not be a problem anymore.

 

Best Regards,

John


Virus-free. www.avast.com
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

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

guest271314
In reply to this post by john larson
This is probably not the pattern that is being proposed though outputs the expected result

    ```class RequestManager {
      constructor() {
        this.successMessage = "Xhr successful.";
        RequestManager.THIS = this;
      }

      makeRequest() {
        var oReq = new XMLHttpRequest();
        oReq.addEventListener("load", this.responseHandler);
        oReq.open("GET", "");
        oReq.send();
      }

      responseHandler(e) {
        console.log(e, this); // `e`: event, `this`: XMLHttpRequest instance
        console.log(RequestManager.THIS.successMessage);
      }

    }

    var reqManager = new RequestManager();

    reqManager.makeRequest();```

On Sat, Mar 9, 2019 at 11:42 AM john larson <[hidden email]> wrote:

Summary of the problem:

“this” keyword in Javascript is context dependent. And this is one of the culprits of most subtle and latent errors in Javascript. Moreover, use of “this” cannot be avoided if we are using classes and trying to reference instance properties.

When “this” is used in callback functions or in functions given to forEach as argument, IDEs rightfully cannot raise any design-time errors, giving developers the false sense of security, but we get run-time errors because “this” is undefined.

There seem to be two work-arounds:

1.      Using arrow functions

2.      Using .bind(this) syntax

Just assuming we forgot to use an arrow function or a .bind(), the IDE will not be able to raise an error and we will encounter the error in run-time.

 

What I propose:

I am proposing a new keyword that will be the alternative of "this" and will always point to the instance of the class. The name of the new keyword can be chosen with consensus from the community such that it would minimize/eliminate collision in existing codebases.

 

Here is a sample js code:

 

class RequestManager{
 
    constructor(){
        this.successMessage = "Xhr successful.";
    }
 
 
    makeRequest() {
        var oReq = new XMLHttpRequest();
        oReq.addEventListener("load", this.responseHandler);
        oReq.open("GET", "www.google.com");
        oReq.send();
    }
 
    responseHandler() {
        window.alert(this.successMessage);
    }
}
 
var reqManager = new RequestManager();
reqManager.makeRequest();

 

This piece of code will alert “undefined” because “this” is undefined in the callback function in strict mode.

Now let’s assume a new keyword is used insetead of “this” that will always point to the class instance.

As per its implementation, as described on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes:

JavaScript classes, introduced in ECMAScript 2015, are primarily syntactical sugar over JavaScript's existing prototype-based inheritance. The class syntax does not introduce a new object-oriented inheritance model to JavaScript.”

So with the new keyword introduced, behind the scenes, previous class could be interpreted as a piece of code along the lines of:

 

var RequestManager = function () {
    var self = this;
    self.successMessage = "Xhr successful";
 
    self.makeRequest = function () {
        var oReq = new XMLHttpRequest();
        oReq.addEventListener("load", responseHandler);
        oReq.open("GET", "www.google.com");
        oReq.send();
    };
 
    var responseHandler = function () {
        window.alert(self.successMessage);
    };
};
var reqManager = new RequestManager();
 
reqManager.makeRequest();

 

I believe this way, we would not have to resort to work-arounds for such a fundamental construct of the language and this would ease developers’ lives as someone forgetting to have used an arrow function or the .bind(this) syntax will not be a problem anymore.

 

Best Regards,

John


Virus-free. www.avast.com
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

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

john larson

First of all, thank you all for taking the time to review the proposal and sharing your valuable opinions. I would like to note that the proposal aims not to add a new capability that was not possible to do before but rather move the standard forward on the way for a modern, better and easier to use language for all the developers. Advancements of the language, or any language in that matter, throughout the last decade also followed a similar path because we were already able to do everything in one way or the other. We actually strive for the same thing, a better Javascript.

 

That being said, let me try to clarify my proposal further by walking you through my thought process:

 

Normally if I try to write a class similar to the sample code I have given in my first email using an object oriented programming language like Java, C# etc., I would be writing something similar to the following:

 

    class RequestManager

    {

        string successMessage = "Xhr successful.";

 

        void makeRequest()

        {

            var oReq = new XMLHttpRequest();

            oReq.addEventListener("load", responseHandler);

            oReq.open("GET""www.google.com");

            oReq.send();

        }

 

        void responseHandler()

        {

            window.alert(successMessage);

        }

    }

 

As you can see, I do not even have to use a special keyword for referring to methods from inside the class. Because they are already in lexical scope. Now, if this can be accomplished in Javascript without hitting some limitation/restriction due to the current state of the language, I think it would be the ideal solution. (This limitation might be the class syntax being just a syntactical sugar or some other reason that I cannot foresee right now and that would require a breaking change.) And I would happily change the proposal that way: “A no-keyword alternative for the “this””. If I should summarize this approach, I can say that every method of the class is going to assume the behavior we now have with arrow functions, but without requiring the use of the “this” and the arrow function syntax.

 

As contrary to the ideal solution, the last thing I would want would be to use a context-dependant keyword like the “this” to refer to methods/properties of the object and then try to set the context right by using binding or arrow functions. This referral should be lexical, not context-dependant. If I have the intent of referring to the instance method/property, that intent should manifest itself right there where I am using this method/property. I shouldn’t be looking at if this takes place inside an arrow function, or if the enclosing method is called with a binding or not. Why should I care about the enclosing of the call, right?

By the way, MDN also mentions the following about the use of arrow functions: “Arrow function expressions are ill suited as methods”.

@Yulia: Thanks for pointing out the decorator approach. But that also seems to deal with the enclosing and tries to solve the problem with a “context binding” approach. The only difference is the way it determines the binding. I am against this binding approach all together. Only the lexical scope of the code should be taken into consideration.

 

So far, I have laid out what I think the ideal solution is and what I think the problematic state we are in right now. And as a middle-ground, in case the ideal solution cannot be applied, I proposed a new keyword to use instead of the “this” so that it will always refer to the instance, regardless of execution context binding. In which case, when you replace the “this” in the problematic sample code in my initial email, it will work just fine. Let’ assume for the sake of this example that the new keyword is “self”:

 

class RequestManager{

 

    constructor(){

        self.successMessage = "Xhr successful.";

    }

 

 

    makeRequest() {

        var oReq = new XMLHttpRequest();

        oReq.addEventListener("load", self.responseHandler);

        oReq.open("GET", "www.google.com");

        oReq.send();

    }

 

    responseHandler() {

        window.alert(self.successMessage);

    }

}

 

var reqManager = new RequestManager();

reqManager.makeRequest();

 

As you can see, self.responseHandler will always point to the responseHandler method no matter whether the enclosing is a method, an arrow function or if it is called using a bind syntax or not.

I would be happy to further address your concerns about this explanation if you have any.

 


On Sun, Mar 10, 2019 at 10:30 PM guest271314 <[hidden email]> wrote:
This is probably not the pattern that is being proposed though outputs the expected result

    ```class RequestManager {
      constructor() {
        this.successMessage = "Xhr successful.";
        RequestManager.THIS = this;
      }

      makeRequest() {
        var oReq = new XMLHttpRequest();
        oReq.addEventListener("load", this.responseHandler);
        oReq.open("GET", "");
        oReq.send();
      }

      responseHandler(e) {
        console.log(e, this); // `e`: event, `this`: XMLHttpRequest instance
        console.log(RequestManager.THIS.successMessage);
      }

    }

    var reqManager = new RequestManager();

    reqManager.makeRequest();```

On Sat, Mar 9, 2019 at 11:42 AM john larson <[hidden email]> wrote:

Summary of the problem:

“this” keyword in Javascript is context dependent. And this is one of the culprits of most subtle and latent errors in Javascript. Moreover, use of “this” cannot be avoided if we are using classes and trying to reference instance properties.

When “this” is used in callback functions or in functions given to forEach as argument, IDEs rightfully cannot raise any design-time errors, giving developers the false sense of security, but we get run-time errors because “this” is undefined.

There seem to be two work-arounds:

1.      Using arrow functions

2.      Using .bind(this) syntax

Just assuming we forgot to use an arrow function or a .bind(), the IDE will not be able to raise an error and we will encounter the error in run-time.

 

What I propose:

I am proposing a new keyword that will be the alternative of "this" and will always point to the instance of the class. The name of the new keyword can be chosen with consensus from the community such that it would minimize/eliminate collision in existing codebases.

 

Here is a sample js code:

 

class RequestManager{
 
    constructor(){
        this.successMessage = "Xhr successful.";
    }
 
 
    makeRequest() {
        var oReq = new XMLHttpRequest();
        oReq.addEventListener("load", this.responseHandler);
        oReq.open("GET", "www.google.com");
        oReq.send();
    }
 
    responseHandler() {
        window.alert(this.successMessage);
    }
}
 
var reqManager = new RequestManager();
reqManager.makeRequest();

 

This piece of code will alert “undefined” because “this” is undefined in the callback function in strict mode.

Now let’s assume a new keyword is used insetead of “this” that will always point to the class instance.

As per its implementation, as described on https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes:

JavaScript classes, introduced in ECMAScript 2015, are primarily syntactical sugar over JavaScript's existing prototype-based inheritance. The class syntax does not introduce a new object-oriented inheritance model to JavaScript.”

So with the new keyword introduced, behind the scenes, previous class could be interpreted as a piece of code along the lines of:

 

var RequestManager = function () {
    var self = this;
    self.successMessage = "Xhr successful";
 
    self.makeRequest = function () {
        var oReq = new XMLHttpRequest();
        oReq.addEventListener("load", responseHandler);
        oReq.open("GET", "www.google.com");
        oReq.send();
    };
 
    var responseHandler = function () {
        window.alert(self.successMessage);
    };
};
var reqManager = new RequestManager();
 
reqManager.makeRequest();

 

I believe this way, we would not have to resort to work-arounds for such a fundamental construct of the language and this would ease developers’ lives as someone forgetting to have used an arrow function or the .bind(this) syntax will not be a problem anymore.

 

Best Regards,

John


Virus-free. www.avast.com
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

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

Rob Ede
In reply to this post by john larson
I would imagine that this can be achieved with bind operator proposal, which already has Babel support, despite no examples showing usage inside a class.

Something like:
`oReq.addEventListener("load", ::this.responseHandler);`
seems to be the syntax that will de-sugar to
`oReq.addEventListener("load", this.responseHandler.bind(this));`
to get you the desired this binding.

I’m surprised this idea hasn't been mentioned yet although things have been moving slowly on that proposal and it seems to need some community support to move along.

Regards,
Rob


References:


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

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

john larson
@Rob: Thanks for pointing out "proposal-bind-operator". I examined the proposal and as far as I understand, it is just another way to create a bound enclosing function. What I am proposing is just the opposite, no binding should take place in the enclosing function. A method call or usage of a property should already have its lexical scope pointing to the class instance and should not need any binding of its enclosing environment to function correctly.

On Mon, Mar 11, 2019 at 4:57 PM Rob Ede <[hidden email]> wrote:
I would imagine that this can be achieved with bind operator proposal, which already has Babel support, despite no examples showing usage inside a class.

Something like:
`oReq.addEventListener("load", ::this.responseHandler);`
seems to be the syntax that will de-sugar to
`oReq.addEventListener("load", this.responseHandler.bind(this));`
to get you the desired this binding.

I’m surprised this idea hasn't been mentioned yet although things have been moving slowly on that proposal and it seems to need some community support to move along.

Regards,
Rob


References:


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

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

Ben Wiley
The main issue here is that you're sort of asking for something too late.

If you reference the "notThis" keyword inside a callback method that has been separated from "its own" class instance, you're now saying "could you please do this all in the context of your instance", but your method doesn't know what its instance is because it never saved a reference.

Alternatively the compiler would notice that the "notThis" keyword is invoked inside a method, and automatically make a bound property on construction. The problem is that you're eagerly making a copy of every method using "notThis" for every instance that exists - eating up a whole bunch of extra memory for large collections - without knowing necessarily that those bound copies will be used. Granted, we're triggering the same problem when folks are using "class property arrow methods" for all their methods in React classes.

Ben

Le lun. 11 mars 2019 11 h 04, john larson <[hidden email]> a écrit :
@Rob: Thanks for pointing out "proposal-bind-operator". I examined the proposal and as far as I understand, it is just another way to create a bound enclosing function. What I am proposing is just the opposite, no binding should take place in the enclosing function. A method call or usage of a property should already have its lexical scope pointing to the class instance and should not need any binding of its enclosing environment to function correctly.

On Mon, Mar 11, 2019 at 4:57 PM Rob Ede <[hidden email]> wrote:
I would imagine that this can be achieved with bind operator proposal, which already has Babel support, despite no examples showing usage inside a class.

Something like:
`oReq.addEventListener("load", ::this.responseHandler);`
seems to be the syntax that will de-sugar to
`oReq.addEventListener("load", this.responseHandler.bind(this));`
to get you the desired this binding.

I’m surprised this idea hasn't been mentioned yet although things have been moving slowly on that proposal and it seems to need some community support to move along.

Regards,
Rob


References:

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

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

john larson

Well, actually this is the same discussion we had with @Jordan Harband. 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. But as I said, it would be insightful to get a js engine expert opinion on this. Having said that, I believe it is just an implementation detail and can be handled one way or the other. I guess the “class property arrow methods in React" example you just provided also supports this notion.


On Mon, Mar 11, 2019 at 6:23 PM Ben Wiley <[hidden email]> wrote:
The main issue here is that you're sort of asking for something too late.

If you reference the "notThis" keyword inside a callback method that has been separated from "its own" class instance, you're now saying "could you please do this all in the context of your instance", but your method doesn't know what its instance is because it never saved a reference.

Alternatively the compiler would notice that the "notThis" keyword is invoked inside a method, and automatically make a bound property on construction. The problem is that you're eagerly making a copy of every method using "notThis" for every instance that exists - eating up a whole bunch of extra memory for large collections - without knowing necessarily that those bound copies will be used. Granted, we're triggering the same problem when folks are using "class property arrow methods" for all their methods in React classes.

Ben

Le lun. 11 mars 2019 11 h 04, john larson <[hidden email]> a écrit :
@Rob: Thanks for pointing out "proposal-bind-operator". I examined the proposal and as far as I understand, it is just another way to create a bound enclosing function. What I am proposing is just the opposite, no binding should take place in the enclosing function. A method call or usage of a property should already have its lexical scope pointing to the class instance and should not need any binding of its enclosing environment to function correctly.

On Mon, Mar 11, 2019 at 4:57 PM Rob Ede <[hidden email]> wrote:
I would imagine that this can be achieved with bind operator proposal, which already has Babel support, despite no examples showing usage inside a class.

Something like:
`oReq.addEventListener("load", ::this.responseHandler);`
seems to be the syntax that will de-sugar to
`oReq.addEventListener("load", this.responseHandler.bind(this));`
to get you the desired this binding.

I’m surprised this idea hasn't been mentioned yet although things have been moving slowly on that proposal and it seems to need some community support to move along.

Regards,
Rob


References:

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

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

Ben Wiley
Whatever the implementation, I'd be surprised to learn that the browser *does* have the information automatically and wouldn't need to store additional memory similar to .bind().

But I'm also not a browser engine expert, so there's that.

Le lun. 11 mars 2019 11 h 55, john larson <[hidden email]> a écrit :

Well, actually this is the same discussion we had with @Jordan Harband. 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. But as I said, it would be insightful to get a js engine expert opinion on this. Having said that, I believe it is just an implementation detail and can be handled one way or the other. I guess the “class property arrow methods in React" example you just provided also supports this notion.


On Mon, Mar 11, 2019 at 6:23 PM Ben Wiley <[hidden email]> wrote:
The main issue here is that you're sort of asking for something too late.

If you reference the "notThis" keyword inside a callback method that has been separated from "its own" class instance, you're now saying "could you please do this all in the context of your instance", but your method doesn't know what its instance is because it never saved a reference.

Alternatively the compiler would notice that the "notThis" keyword is invoked inside a method, and automatically make a bound property on construction. The problem is that you're eagerly making a copy of every method using "notThis" for every instance that exists - eating up a whole bunch of extra memory for large collections - without knowing necessarily that those bound copies will be used. Granted, we're triggering the same problem when folks are using "class property arrow methods" for all their methods in React classes.

Ben

Le lun. 11 mars 2019 11 h 04, john larson <[hidden email]> a écrit :
@Rob: Thanks for pointing out "proposal-bind-operator". I examined the proposal and as far as I understand, it is just another way to create a bound enclosing function. What I am proposing is just the opposite, no binding should take place in the enclosing function. A method call or usage of a property should already have its lexical scope pointing to the class instance and should not need any binding of its enclosing environment to function correctly.

On Mon, Mar 11, 2019 at 4:57 PM Rob Ede <[hidden email]> wrote:
I would imagine that this can be achieved with bind operator proposal, which already has Babel support, despite no examples showing usage inside a class.

Something like:
`oReq.addEventListener("load", ::this.responseHandler);`
seems to be the syntax that will de-sugar to
`oReq.addEventListener("load", this.responseHandler.bind(this));`
to get you the desired this binding.

I’m surprised this idea hasn't been mentioned yet although things have been moving slowly on that proposal and it seems to need some community support to move along.

Regards,
Rob


References:

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

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

Bergi
In reply to this post by john larson
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
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

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

Isiah Meadows-2
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 <[hidden email]> 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
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

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

john larson
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 <[hidden email]> 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 <[hidden email]> 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
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
12