このバインディング

14566 ワード

このバインディング
:バインドは、識別子を値に関連付けるプロセスを意味します.たとえば、変数宣言は、変数名(識別子)と保存済みメモリ領域をバインドするアドレスです.このバインドは、this(キーワードに分類されますが、識別子として機能します)とthisがバインドするオブジェクトをバインドします.
💡出典:Modern JavaScript Deep Dive:JavaScriptの基本概念と動作原理/李雄模知音/ウィキペディアthisバインドの問題を解決する3つの方法
まずは問題になるハーモニー…!!
export default class Field {
  constructor() {
    this.field.addEventListener('click', this.onClick);
  }
  
   onClick(event) {
    const target = event.target;
    if (target.matches('.carrot')) {
      target.remove();
      sound.playCarrot();
      this.onItemClick && this.onItemClick('carrot');
    } else if (target.matches('.bug')) {
      this.onItemClick && this.onItemClick('bug');
    }
  }
  // 불필요한 내용들은 삭제하였습니다.
ケース👩🏻‍💻
constructor
1.addEventListenerthis.onClickが登録されている.
2.fieldでアイテムをクリックするとコールバック関数が呼び出される(this.onClick).
onClick
1.クラスのthisonItemClickがある場合は、このアイテムを呼び出してクリックします:)
質問する🔥
他の言語では問題ではありませんが、JavaScriptでは不自然です.
どうしたんですか.
constructor() {
    this.field.addEventListener('click', this.onClick);
  }
why?
関数をパラメータとして位置に渡すと、クラス情報は一緒に渡されないためです.
すなわち、this.onClickは、Fieldクラスにおけるメンバフェース数である.
したがって、this.onClickを転送すると、Classの情報を同時に転送する可能性があります.
JavaScriptではクラスは無視され、関数のみが渡されます.
この言葉の意味は、this.onClickを含む類の情報はコールバックで伝達できない…!?
つまり、このthis.onClickが伝えられた後
onClick(event) {
    const target = event.target;
    if (target.matches('.carrot')) {
      target.remove();
      sound.playCarrot();
      this.onItemClick && this.onItemClick('carrot');
    } else if (target.matches('.bug')) {
      this.onItemClick && this.onItemClick('bug');
    }
もしonClickにthis.が入っていたら、つまり、このクラスにonClickが入っていたら、このクラスのonClickを呼ぶべきだ!それでも
実際、このonClikが他の場所にコールバックされると、この情報は存在しなくなり、クリックアイテムはundefined状態になります.
解決策🏝
クラス内の関数を誰かに渡すと、クラス情報は無視されます.したがって、クラス情報を無視したくない場合は、関数をクラスにバインドする必要があります.
1.関数を直接バインドする方法
export default class Field {
  constructor() {
    this.onClick = this.onClick.bind(this);
    this.field.addEventListener('click', this.onClick);
  }
このように一つ一つ記入することができますが、通常はそうしません.
2. arrow function
export default class Field {
  constructor() {
    this.field.addEventListener('click', (event) => this.onClick(event));
  }
arrow関数はこれを保持するので、この方法をよく使います.
3.その他の方法
export default class Field {
  constructor() {
    this.field.addEventListener('click', this.onClick);
  }
 
 onClick = (event) => {
    const target = event.target;
    if (target.matches('.carrot')) {
      target.remove();
      sound.playCarrot();
      this.onItemClick && this.onItemClick('carrot');
    } else if (target.matches('.bug')) {
      this.onItemClick && this.onItemClick('bug');
    }
  }; 
onClick自体を変数に置き換え、arrow関数を指すと自動的にバインドされます.
整理する📒
クラスの関数を別のコールバックに渡すと、関数を含むクラスの情報は消えます.したがって、クラスと関数(thisと関数をバインドできる)をバインドするバインドがあります.具体的には、コード「関数、バインドクラス」(1番)を記述したり、arrow関数を使用したりすることができます.