Better support for "losing this" in instance methods passed as functions to event handlers

Topics: Language Specification
Oct 20, 2013 at 11:45 PM
I just worked over a 2,000 line enterprise JavaScript module that I wrote, converted it to typescript, and found a number of annoyances. Chief among them is that I removed the whole self = this followed by 100+ usages of "self." in favor of "this.", and now all my jQuery, jstree, and jQuery-ui bindings need $.proxy( this.methodName, this). It would be very useful if the bind methods from jQuery and jQuery-ui were able to be annotated that they "lose this" and then the typescript compiler in turn could offer warnings when instance methods were passed into them. Additionally, a recommendation to use $.proxy( this.methodName, this ) would be useful.

Similarly, it might be nice if there were certain compiler-assisted corrections to user code which might perform said replacement integrated into the VS 2013 plugin module.
Oct 21, 2013 at 3:18 PM
Some sample code would make things more interesting.
Nov 21, 2013 at 5:47 PM
Edited Nov 21, 2013 at 5:49 PM
I'd like to contribute on this issue. I'm passing for similar problems, and I can show some code.

Imagine you have the following simplified markup:
<div data=bind="click: loadNextItem">
and the following simplified model:
class Model
{
    currentItem = ko.observable();
    loadNextItem()
    {
        var currentItem = this.currentItem(); //<-- boom. We can't get the current item
    }
}
In javascript, it could be easily fixed by storing the current "class" into a variable, for example, "_this" in the beginning.
But it is not possible in typescript, which leads to some workaround you find over the web.

One of the solutions I found is:
class Model
{
    currentItem = ko.observable();
    loadNextItem;
    constructor()
    {
        this.loadNextItem = () =>
        {
            var currentItem = this.currentItem(); //got item
        }
    }
}
But, for me, that is not the solution, because it breaks the capsule! With this, if I need to find where the method is implemented, instead of looking at the method itself, I need to find if this is implemented on a constructor, or who knows where the developer put it. What if he decided to put the implementation in an external class, just because there is no a standard place for it?

Also, I think the constructor is a better place to initialize things, not to define things. =)

I suggest some form of accessing the current class, or, following the javascript way, give us a form to create our own "_this" variables.
Coordinator
Nov 21, 2013 at 6:54 PM
This is basically an issue of behavioral semantics. Much like how in other languages, some methods are threadsafe and some aren't, in JavaScript some methods are "this-safe" and some aren't. It's up to you to manage that behavior.

You can use this syntax form to more elegantly write your class:
    class Model
    {
        currentItem = ko.observable();
        
        /** This function is safe to use in callbacks */
        loadNextItem = () => {
            var currentItem = this.currentItem();
        }
    }
Nov 21, 2013 at 8:52 PM
Cool. I like this is the solution!

I've tried some unsucessful way of doing this in the past, but now you pointed me the right sintax!

Thanks.