Typescript "this" внутри метода класса


Я знаю, что это, вероятно, болезненно простой, но у меня есть трудное время, обернув мою голову вокруг него.

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

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

}

похоже, что мне нужен прокси, поэтому давайте скажем, используя Jquery

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

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

}

но исходя из фона Actionscript 3, я не совсем уверен, что здесь происходит. Извините, я не уверен, где начинается Javascript и заканчивается TypeScript.

updateProxy: () => void

а также, я не уверен, что я делаю это правильно. Последнее, чего я хочу-это большая часть моего класса имеет функцию a (), к которой нужно обращаться с помощью aProxy() как я чувствую, что я пишу то же самое дважды? Это нормально?

5 51

5 ответов:

если вы хотите this захватил способ TypeScript сделать это с помощью функций стрелки. Цитируя Андерса:

The this в функции стрелки лексически ограничен

вот как я хотел бы использовать это в своих интересах:

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

посмотреть это в TypeScript Playground

вы можете видеть, что в сгенерированном JavaScript this плен за пределами функции звоните:

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

так this значение внутри вызова функции (которая может быть window) не будет использоваться.

чтобы узнать больше: "понимание this in TypeScript "(4:05) – YouTube

Если вы пишете свои методы, как это, " это " будет рассматриваться так, как вы ожидаете.

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

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

другой вариант-привязать " это " к вызову функции:

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

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

проблема возникает, когда вы передаете функцию в качестве обратного вызова. К моменту выполнения обратного вызова значение "this" может быть изменено на окно, элемент управления, вызывающий обратный вызов, или что-то еще.

убедитесь, что вы всегда используете лямбда-выражение в точке передачи ссылки на вызываемую функцию. Например

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

это компилируется к чему-то вроде

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

потому что функция addFile вызывается на a конкретная ссылка на объект (_this) он не использует "это" вызывающего, но вместо этого значение _this.

см. страницу 72 спецификации языка машинописи https://github.com/Microsoft/TypeScript/blob/master/doc/TypeScript%20Language%20Specification.pdf?raw=true

Выражения Функции Стрелка

пример

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

использование выражения функции стрелки заставляет обратный вызов иметь то же самое, что и окружающий метод "старт". Написание обратного вызова в качестве стандартного выражения функции он становится необходимо вручную организуйте доступ к окружающему этому, например, скопировав его в локальная переменная:

это фактический сгенерированный Javascript:

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

короче, ключевое слово this всегда ссылается на объект, который вызвал функцию.

в Javascript, поскольку функции - это просто переменные, вы можете передавать их.

пример:

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

когда вы делаете следующее с jQuery:

$.proxy(this.update, this);

то, что вы делаете, переопределяет этот контекст. За кулисами jQuery будет guive вам это:

$.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
  }
};