Typescript “this” inside a class method

前端 未结 7 1390
温柔的废话
温柔的废话 2020-11-30 02:45

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

class Main
{
     constructor()
     {
         requestAni         


        
相关标签:
7条回答
  • 2020-11-30 03:12

    Very late to the party, but I think it is very important for future visitors of this question to consider the following:

    The other answers, including the accepted one, miss a crucial point:

    myFunction() { ... }
    

    and

    myFunction = () => { ... }
    

    are not the same thing "with the exception that the latter captures this".

    The first syntax creates a method on the prototype, while the second syntax creates a property on the object whos value is a function (that also happens to capture this). You can see this clearly in the transpiled JavaScript.

    To be complete:

    myFunction = function() { ... }
    

    would be the same als the second syntax, but without the capturing.

    So, using the arrow syntax in most cases will fix your problem of binding to the object, but it's not the same and there are many situations where you do want to have a proper function on the prototype in stead of a property.

    In these cases using a proxy or .bind() actually is the correct solution. (Although suffering readability.)

    More reading here (not primarily about TypeScript, but the principles stand):

    https://medium.com/@charpeni/arrow-functions-in-class-properties-might-not-be-as-great-as-we-think-3b3551c440b1

    https://ponyfoo.com/articles/binding-methods-to-class-instance-objects

    0 讨论(0)
  • 2020-11-30 03:13

    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);
     }
    };
    
    0 讨论(0)
  • 2020-11-30 03:14

    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

    0 讨论(0)
  • 2020-11-30 03:15

    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.

    0 讨论(0)
  • 2020-11-30 03:18

    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));
        }
    }
    
    0 讨论(0)
  • 2020-11-30 03:23

    How about doing it this way? Declare a global variable of type "myClass" and initialise it in the constructor of the class:

    var _self: myClass;
    
    class myClass {
        classScopeVar: string = "hello";
    
        constructor() {
            _self = this;
        }
    
        alerter() {
            setTimeout(function () {
                alert(_self.classScopeVar)
            }, 500);
        }
    }
    
    var classInstance = new myClass();
    classInstance.alerter();
    

    Note: It is important NOT to use "self" as it as a special meaning already.

    0 讨论(0)
提交回复
热议问题