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);
}
};