1. ホーム
  2. typescript

[解決済み] TypeScript "this" scoping issue when called in jquery callback.

2022-09-25 15:45:50

質問

TypeScriptで"this"のスコープを処理するための最適なアプローチがわかりません。

私がTypeScriptに変換しているコードによくあるパターンの例です。

class DemonstrateScopingProblems {
    private status = "blah";
    public run() {
        alert(this.status);
    }
}

var thisTest = new DemonstrateScopingProblems();
// works as expected, displays "blah":
thisTest.run(); 
// doesn't work; this is scoped to be the document so this.status is undefined:
$(document).ready(thisTest.run); 

さて、この呼び出しを変更すると...

$(document).ready(thisTest.run.bind(thisTest));

...これは動作します。しかし、これはちょっと恐ろしいことです。つまり、ある状況下ではコードはすべてコンパイルできてうまく動作しますが、スコープをバインドするのを忘れると壊れてしまうのです。

私は、クラスを使用するときに "this" が何にスコープされているかを気にする必要がないように、クラス内でそれを行う方法を望みます。

何か提案はありますか?

更新情報

太い矢印を使うのも効果的な方法です。

class DemonstrateScopingProblems {
    private status = "blah";

    public run = () => {
        alert(this.status);
    }
}

それは有効な方法なのでしょうか?

どのように解決するのですか?

ここにはいくつかの選択肢があり、それぞれにトレードオフがあります。残念ながら、明らかな最適解はなく、アプリケーションに依存します。

自動クラスバインディング

ご質問の通りです。

class DemonstrateScopingProblems {
    private status = "blah";

    public run = () => {
        alert(this.status);
    }
}

  • 良い/悪い: これは、クラスのインスタンスごとにメソッドごとに追加のクロージャを作成します。このメソッドが通常メソッド呼び出しでのみ使用される場合、これは過剰な要求です。しかし、コールバックの位置で多く使われるのであれば、クラスのインスタンスがキャプチャする方が効率的です。 this コンテキストを取得する方が効率的です。
  • 良い点: 外部呼び出し元が this コンテキスト
  • 良いですね。TypeScriptでのタイプセーフ
  • 良い。関数にパラメータがある場合、余分な作業がない
  • 悪い点 派生クラスは、この方法で書かれたベースクラスのメソッドを super.
  • 悪い点 どのメソッドが "pre-bound" で、どれがそうでないかの正確なセマンティクスは、あなたのクラスとその消費者の間に追加の非タイプセーフ契約を作成します。

関数.bind

また、図のように

$(document).ready(thisTest.run.bind(thisTest));

  • 良い/悪い 最初の方法と比較して、メモリ/性能のトレードオフが反対になっている
  • 良い点 関数にパラメータがある場合、余分な作業がない
  • 悪い点 TypeScriptでは、これは現在、型安全性を持っていません。
  • 悪い点 ECMAScript 5 でのみ使用可能。
  • 悪い点 インスタンス名を 2 回入力する必要がある

太い矢印

TypeScriptの場合(ここでは説明のためにダミーのパラメータをいくつか付けて表示しています)。

$(document).ready((n, m) => thisTest.run(n, m));

  • 良い/悪い 最初の方法と比較して、メモリ/性能のトレードオフが反対になっている
  • 良い点: TypeScriptでは、100%の型安全性を持つ。
  • 良い。ECMAScript 3 で動作する。
  • 良い。インスタンス名を一度だけ入力する必要がある
  • 悪い点 パラメータを2回入力する必要がある
  • 悪い点 可変長のパラメータでは動作しない