Typescript “this” inside a class method

匿名 (未验证) 提交于 2019-12-03 01:07:01

问题:

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?

回答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



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


回答3:

The problem arises when you pass a function as a callback. By the time the callback has executed the value of "this" could have changed to the Window, the control invoking the callback, or something else.

Make sure you always use a lambda expression at the point you pass a reference to the function to be called back. For example

public addFile(file) {   this.files.push(file); } //Not like this someObject.doSomething(addFile); //but instead, like this someObject.doSomething( (file) => addFile(file) ); 

This compiles to something like

this.addFile(file) {   this.files.push(file); } var _this = this; someObject.doSomething(_this.addFile); 

Because the addFile function is being called on a specific object reference (_this) it does not use the "this" of the invoker but instead the value of _this.



回答4:

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


回答5:

In short, the this keyword always has a reference to the object that called the function.

In Javascript, since functions are just variables, you can pass them around.

Example:

var x = {    localvar: 5,     test: function(){       alert(this.localvar);    } };  x.test() // outputs 5  var y; y.somemethod = x.test; // assign the function test from x to the 'property' somemethod on y y.test();              // outputs undefined, this now points to y and y has no localvar  y.localvar = "super dooper string"; y.test();              // outputs super dooper string 

When you do the following with jQuery:

$.proxy(this.update, this); 

What you are doing is overriding that context. Behind the scenes jQuery will guive you this:

$.proxy = function(fnc, scope){   return function(){      return fnc.apply(scope);  // apply is a method on a function that calls that function with a given this value   } }; 


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!