Typescript "this" inside a class method

I know this is probably painfully basic, but i am having a tough time wrapping my head around it.

class Main
{
     constructor()
     {
         requestAnimationFrame(this.update);  //fine    
     }

     update(): void
     {
         requestAnimationFrame(this.update);  //error, because this is window
     }

}

It appears to be the case that I need a proxy, so lets say using Jquery

class Main
{
     constructor()
     {
         this.updateProxy = $.proxy(this.update, this);
         requestAnimationFrame(this.updateProxy);  //fine    
     }

     updateProxy: () => void
     update(): void
     {
         requestAnimationFrame(this.updateProxy);  //fine
     }

}

But coming from an Actionscript 3 background, I am not really sure what is happening here. Sorry I am not sure where Javascript begins and TypeScript ends.

updateProxy: () => void

And also, I am not convinced I am doing this right. The last thing I want is most of my class having a a() function which needs to be accessed with aProxy() as I feel I am writing the same thing twice? Is it normal?


Solution 1:

If you want this captured the TypeScript way of doing this is via arrow functions. To quote Anders:

The this in arrow functions is lexically scoped

Here is the way I like to use this to my advantage:

class test{
    // Use arrow functions
    func1=(arg:string)=>{
            return arg+" yeah" + this.prop;
    }
    func2=(arg:number)=>{
            return arg+10 + this.prop;
    }       

    // some property on this
    prop = 10;      
}

View this in the TypeScript Playground

You can see that in the generated JavaScript this is captured outside the function call:

var _this = this;
this.prop = 10;
this.func1 = function (arg) {
    return arg + " yeah" + _this.prop;
};

so the this value inside the function call (which could be window) would not be used.

To learn more: “Understanding this in TypeScript” (4:05) – YouTube

Solution 2:

If you write your methods like this, 'this' will be treated the way you expect.

class Main
{
    constructor()
    {
        requestAnimationFrame(() => this.update());
    }

    update(): void
    {
        requestAnimationFrame(() => this.update());
    }
}

Another option would be to bind 'this' to the function call:

class Main
{
    constructor()
    {
        requestAnimationFrame(this.update.bind(this));
    }

    update(): void
    {
        requestAnimationFrame(this.update.bind(this));
    }
}

Solution 3:

See page 72 of the typescript language specification https://github.com/Microsoft/TypeScript/blob/master/doc/TypeScript%20Language%20Specification.pdf?raw=true

Arrow Function Expressions

In the example

class Messenger {
 message = "Hello World";
 start() {
 setTimeout(() => alert(this.message), 3000);
 }
};
var messenger = new Messenger();
messenger.start();

the use of an arrow function expression causes the callback to have the same this as the surrounding ‘start’ method. Writing the callback as a standard function expression it becomes necessary to manually arrange access to the surrounding this, for example by copying it into a local variable:

This is the actual generated Javascript:

class Messenger {
 message = "Hello World";
 start() {
 var _this = this;
 setTimeout(function() { alert(_this.message); }, 3000);
 }
};