web-dev-qa-db-ja.com

クラスメソッド内のタイプスクリプト「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()でアクセスする必要があります。それは普通ですか?

71
Clark

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プレイグラウンドでこれを表示

生成されたJavaScriptでthisがキャプチャされていることがわかりますoutside関数呼び出し:

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

そのため、関数呼び出し内のthis値(windowの場合もあります)は使用されません。

詳細: 「TypeScriptのthisを理解する」(4:05)– YouTube

100
basarat

このようなメソッドを記述する場合、「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));
    }
}
17
joelnet

TypeScript言語仕様の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();

矢印関数式を使用すると、コールバックは周囲の「開始」メソッドと同じthisを持ちます。コールバックを標準の関数式として記述すると、たとえばローカル変数にコピーするなどして、周囲のこれへのアクセスを手動で調整する必要があります。

これは、実際に生成されたJavascriptです。

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

この問題は、関数をコールバックとして渡すときに発生します。コールバックが実行されるまでに、「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の値を使用します。

4
Peter Morris

要するに、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は次のことを示します。

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

パーティーに非常に遅れましたが、この質問の今後の訪問者にとって次のことを考慮することが非常に重要だと思います。

受け入れられたものを含む他の答えは、重要な点を見逃しています。

_myFunction() { ... }
_

そして

_myFunction = () => { ... }
_

arenot「後者がthisをキャプチャすることを除いて」と同じことです。

最初の構文はプロトタイプのメソッドを作成し、2番目の構文は値が関数であるオブジェクトのプロパティを作成します(これはたまたまthisをキャプチャします)。これは、変換されたJavaScriptで明確に確認できます。

完了するには:

_myFunction = function() { ... }
_

2番目の構文と同じですが、キャプチャは行いません。

そのため、矢印構文[ほとんどの場合プロパティの。

これらの場合、プロキシまたは.bind()を実際に使用するとisが正しい解決策になります。 (読みやすさに苦しんでいますが。)

ここでさらに読む(主にTypeScriptについてではなく、原則が成り立つ):

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

1
Karim Ayachi