Programing

클래스 메서드 내부의 타이프 스크립트 "this"

lottogame 2020. 10. 27. 07:46
반응형

클래스 메서드 내부의 타이프 스크립트 "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

또한 제가이 일을 제대로하고 있다고 확신하지 못합니다. 내가 원하는 마지막 것은 내가 aProxy()같은 것을 두 번 쓰고 있다고 느낄 때 액세스 해야하는 aa () 함수를 가진 대부분의 클래스입니다 . 정상인가요?


this캡처 하려는 경우 TypeScript 방식으로 화살표 기능을 사용합니다. Anders를 인용하려면 :

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)은 사용되지 않습니다.

자세히 알아보기 : " thisTypeScript 이해 "(4:05) – YouTube


이와 같이 메소드를 작성하면 'this'가 예상대로 처리됩니다.

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

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

또 다른 옵션은 'this'를 함수 호출에 바인딩하는 것입니다.

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

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

함수를 콜백으로 전달할 때 문제가 발생합니다. 콜백이 실행될 때까지 "this"의 값은 Window, 콜백을 호출하는 컨트롤 또는 다른 것으로 변경되었을 수 있습니다.

콜백 할 함수에 대한 참조를 전달할 때 항상 람다 식을 사용해야합니다. 예를 들면

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 함수는 특정 개체 참조 (_this)에서 호출되기 때문에 호출자의 "this"를 사용하지 않고 대신 _this의 값을 사용합니다.


타이프 스크립트 언어 사양 https://github.com/Microsoft/TypeScript/blob/master/doc/TypeScript%20Language%20Specification.pdf?raw=true의 72 페이지를 참조하십시오.

화살표 함수 표현식

예에서

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

화살표 함수 표현식을 사용하면 콜백이 주변의 'start'메소드와 동일한 값을 갖게됩니다. 콜백을 표준 함수 표현식으로 작성하려면 주변 변수에 대한 액세스를 수동으로 정렬해야합니다 (예 : 로컬 변수에 복사).

This is the actual generated Javascript:

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

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

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

참고URL : https://stackoverflow.com/questions/16157839/typescript-this-inside-a-class-method

반응형